From 125748c55e9526bf587858350ab7d62c2f3a2d34 Mon Sep 17 00:00:00 2001 From: yaochaonan Date: Mon, 21 Nov 2022 14:03:47 +0800 Subject: [PATCH 01/14] =?UTF-8?q?Add=20import=20*=EF=BC=8Cimport=20{a,b}?= =?UTF-8?q?=20mode=20when=20ESM=20require=20CommonJS=20-------------------?= =?UTF-8?q?--------------------------------------=20https://gitee.com/open?= =?UTF-8?q?harmony/arkcompiler=5Fets=5Fruntime/issues/I626AP=3Ffrom=3Dproj?= =?UTF-8?q?ect-issue=201.=20import=20*=20:In=20GetModuleNamespaceInternal?= =?UTF-8?q?=20interface,=20add=20commomjs=20case.=202.=20import=20{a,=20b}?= =?UTF-8?q?:=20execute=20CJSmodule=20first,then=20instantiate,and=20link?= =?UTF-8?q?=20with=20ESM.=203.=20import=20default=20:if=20cacheModule=20is?= =?UTF-8?q?=20not=20CjsExports,=20means=20default=20export.=20------------?= =?UTF-8?q?---------------------------------------------=20Signed-off-by:?= =?UTF-8?q?=20yaochaonan=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I4a35e37f51651618b30dab6ce0e5a929e82dd149 --- ecmascript/module/js_module_manager.cpp | 22 ++- ecmascript/module/js_module_source_text.cpp | 143 ++++++++++++++++-- ecmascript/module/js_module_source_text.h | 15 +- ecmascript/require/js_cjs_module.cpp | 3 +- test/moduletest/moduleUseCjs/BUILD.gn | 10 +- .../moduletest/moduleUseCjs/expect_output.txt | 3 + test/moduletest/moduleUseCjs/moduleUseCjs.js | 8 +- test/moduletest/moduleUseCjs/someArgsCjs.js | 26 ++++ 8 files changed, 212 insertions(+), 18 deletions(-) create mode 100644 test/moduletest/moduleUseCjs/someArgsCjs.js diff --git a/ecmascript/module/js_module_manager.cpp b/ecmascript/module/js_module_manager.cpp index ebb32460c0..ccc304e707 100644 --- a/ecmascript/module/js_module_manager.cpp +++ b/ecmascript/module/js_module_manager.cpp @@ -93,7 +93,20 @@ JSTaggedValue ModuleManager::GetModuleValueOutterInternal(int32_t index, JSTagge SourceTextModule *module = SourceTextModule::Cast(resolvedModule.GetTaggedObject()); if (module->GetTypes() == ModuleTypes::CJSMODULE) { JSHandle cjsModuleName(thread, module->GetEcmaModuleFilename()); - return CjsModule::SearchFromModuleCache(thread, cjsModuleName).GetTaggedValue(); + JSTaggedValue cjsExports = CjsModule::SearchFromModuleCache(thread, cjsModuleName).GetTaggedValue(); + // if cjsModule is not CjsExports, means cjs uses default exports. + if (!cjsExports.IsCjsExports()) { + if (cjsExports.IsHole()) { + LOG_FULL(FATAL) << "CAN NOT SEARCH FROM CJSMODULECACHE"; + } + return cjsExports; + } + int32_t idx = binding->GetIndex(); + JSObject *cjsObject = JSObject::Cast(cjsExports); + JSHClass *jsHclass = cjsObject->GetJSHClass(); + LayoutInfo *layoutInfo = LayoutInfo::Cast(jsHclass->GetLayout().GetTaggedObject()); + PropertyAttributes attr = layoutInfo->GetAttr(idx); + return cjsObject->GetProperty(jsHclass, attr); } return SourceTextModule::Cast(resolvedModule.GetTaggedObject())->GetModuleValue(thread, binding->GetIndex(), false); @@ -502,7 +515,12 @@ JSTaggedValue ModuleManager::GetModuleNamespaceInternal(int32_t index, JSTaggedV requiredModule = SourceTextModule::HostResolveImportedModuleWithMerge(thread, JSHandle(thread, module), JSHandle(thread, moduleName)); } - + // if requiredModule is CommonJS + if (requiredModule->GetTypes() == ModuleTypes::CJSMODULE) { + JSHandle cjsModuleName(thread, requiredModule->GetEcmaModuleFilename()); + return CjsModule::SearchFromModuleCache(thread, cjsModuleName).GetTaggedValue(); + } + // if requiredModule is ESM JSHandle moduleNamespace = SourceTextModule::GetModuleNamespace(thread, requiredModule); ASSERT(moduleNamespace->IsModuleNamespace()); return moduleNamespace.GetTaggedValue(); diff --git a/ecmascript/module/js_module_source_text.cpp b/ecmascript/module/js_module_source_text.cpp index 8d9a9663a5..ff5485de69 100644 --- a/ecmascript/module/js_module_source_text.cpp +++ b/ecmascript/module/js_module_source_text.cpp @@ -122,22 +122,69 @@ JSHandle SourceTextModule::HostResolveImportedModule(JSThread return thread->GetEcmaVM()->GetModuleManager()->HostResolveImportedModule(baseFilename, moduleFilename); } +bool SourceTextModule::CheckCircularImport(const JSHandle &module, + const JSHandle &exportName, + CVector, JSHandle>> &resolveSet) +{ + for (auto rr : resolveSet) { + // a. If module and r.[[Module]] are the same Module Record and + // SameValue(exportName, r.[[ExportName]]) is true, then + if (JSTaggedValue::SameValue(rr.first.GetTaggedValue(), module.GetTaggedValue()) && + JSTaggedValue::SameValue(rr.second, exportName)) { + // i. Assert: This is a circular import request. + // ii. Return true. + return true; + } + } + return false; +} + +JSHandle SourceTextModule::ResolveCjsExport(JSThread *thread, const JSHandle &module, + const JSHandle &cjsModule, + const JSHandle &exportName, + CVector, JSHandle>> &resolveSet) +{ + // 1. Let module be this Source Text Module Record. + auto globalConstants = thread->GlobalConstants(); + // Check if circular import request. + // 2.For each Record { [[Module]], [[ExportName]] } r in resolveSet, do + if (CheckCircularImport(module, exportName, resolveSet)) { + return globalConstants->GetHandledNull(); + } + // 3. Append the Record { [[Module]]: module, [[ExportName]]: exportName } to resolveSet. + resolveSet.emplace_back(std::make_pair(module, exportName)); + // 4. if cjsModule IsCjsExports, means the cjs module has multiple outputs + if (cjsModule->IsCjsExports()) { + JSHClass *jsHclass = JSObject::Cast(cjsModule.GetTaggedValue())->GetJSHClass(); + // Get layoutInfo and compare the input and output names of files + LayoutInfo *layoutInfo = LayoutInfo::Cast(jsHclass->GetLayout().GetTaggedObject()); + if (layoutInfo->NumberOfElements() != 0) { + JSHandle resolution = ResolveCjsLocalExport(thread, layoutInfo, exportName, module); + if (!resolution->IsUndefined()) { + return resolution; + } + } + } + // 5. If cjsModule != IsCjsExports, means the cjs module use default output + JSHandle defaultString = globalConstants->GetHandledDefaultString(); + if (JSTaggedValue::SameValue(exportName, defaultString)) { + // bind with a number + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + return JSHandle::Cast(factory->NewResolvedIndexBindingRecord(module, -1)); + } + return globalConstants->GetHandledNull(); +} + JSHandle SourceTextModule::ResolveExport(JSThread *thread, const JSHandle &module, const JSHandle &exportName, CVector, JSHandle>> &resolveSet) { // 1. Let module be this Source Text Module Record. - // 2. For each Record { [[Module]], [[ExportName]] } r in resolveSet, do auto globalConstants = thread->GlobalConstants(); - for (auto rr : resolveSet) { - // a. If module and r.[[Module]] are the same Module Record and - // SameValue(exportName, r.[[ExportName]]) is true, then - if (JSTaggedValue::SameValue(rr.first.GetTaggedValue(), module.GetTaggedValue()) && - JSTaggedValue::SameValue(rr.second, exportName)) { - // i. Assert: This is a circular import request. - // ii. Return null. - return globalConstants->GetHandledNull(); - } + // Check if circular import request. + // 2.For each Record { [[Module]], [[ExportName]] } r in resolveSet, do + if (CheckCircularImport(module, exportName, resolveSet)) { + return globalConstants->GetHandledNull(); } // 3. Append the Record { [[Module]]: module, [[ExportName]]: exportName } to resolveSet. resolveSet.emplace_back(std::make_pair(module, exportName)); @@ -190,6 +237,60 @@ JSHandle SourceTextModule::ResolveExport(JSThread *thread, const return starResolution; } +void SourceTextModule::CJSInstantiate(JSThread *thread, const JSHandle &module, + const JSHandle &requiredModule) +{ + JSHandle cjsModuleName(thread, requiredModule->GetEcmaModuleFilename()); + // Get exported cjs module + JSHandle cjsExports = CjsModule::SearchFromModuleCache(thread, cjsModuleName); + // Get esm environment + JSHandle moduleEnvironment(thread, SourceTextModule::Cast( + module.GetTaggedValue().GetTaggedObject())->GetEnvironment()); + auto globalConstants = thread->GlobalConstants(); + if (moduleEnvironment->IsUndefined()) { + CString msg = "moduleEnvironment is Undefined"; + THROW_ERROR(thread, ErrorType::RANGE_ERROR, msg.c_str()); + } + JSHandle environment(thread, TaggedArray::Cast(moduleEnvironment->GetTaggedObject())); + size_t length = environment->GetLength(); + JSHandle importEntries(thread, module->GetImportEntries()); + JSMutableHandle host(thread, globalConstants->GetUndefined()); + JSMutableHandle moduleRequest(thread, globalConstants->GetUndefined()); + JSMutableHandle importName(thread, globalConstants->GetUndefined()); + // update required module + for (size_t idx = 0; idx < length; idx++) { + JSTaggedValue resolvedBinding = environment->Get(idx); + // if resolvedBinding.IsHole(), means that importname is * . + if (resolvedBinding.IsHole()) { + continue; + } + ResolvedIndexBinding *binding = ResolvedIndexBinding::Cast(resolvedBinding.GetTaggedObject()); + JSTaggedValue resolvedModule = binding->GetModule(); + JSHandle requestedModule(thread, resolvedModule); + JSHandle moduleName(thread, requestedModule->GetEcmaModuleFilename()); + // if not the same module, then don't have to update + if (!JSTaggedValue::SameValue(moduleName, cjsModuleName)) { + continue; + } + // rebinding here + host.Update(importEntries->Get(idx)); + importName.Update(host->GetImportName()); + // i. Let resolution be ? importedModule.ResolveExport(in.[[ImportName]], « »). + CVector, JSHandle>> resolveSet; + JSHandle resolution = + SourceTextModule::ResolveCjsExport(thread, requestedModule, cjsExports, importName, resolveSet); + // ii. If resolution is null or "ambiguous", throw a SyntaxError exception. + if (resolution->IsNull() || resolution->IsString()) { + CString msg = "find importName " + ConvertToString(importName.GetTaggedValue()) + " failed"; + THROW_ERROR(thread, ErrorType::SYNTAX_ERROR, msg.c_str()); + } + // iii. Call envRec.CreateImportBinding( + // in.[[LocalName]], resolution.[[Module]], resolution.[[BindingName]]). + environment->Set(thread, idx, resolution); + } + module->SetEnvironment(thread, environment); +} + int SourceTextModule::Instantiate(JSThread *thread, const JSHandle &module) { // 1. Let module be this Source Text Module Record. @@ -626,6 +727,10 @@ int SourceTextModule::InnerModuleEvaluation(JSThread *thread, const JSHandleGetDFSAncestorIndex(), requiredModule->GetDFSAncestorIndex()); module->SetDFSAncestorIndex(dfsAncIdx); } + // if requiredModule == CommonJS, instantiate here (after CommonJS execution). + if ((requiredModule->GetTypes() == ModuleTypes::CJSMODULE)) { + CJSInstantiate(thread, module, requiredModule); + } } } @@ -963,6 +1068,20 @@ void SourceTextModule::AddExportName(JSThread *thread, const JSTaggedValue &expo } } +JSHandle SourceTextModule::ResolveCjsLocalExport(JSThread *thread, + LayoutInfo *layoutInfo, + const JSHandle &exportName, + const JSHandle &module) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + int propertiesNumber = layoutInfo->NumberOfElements(); + int idx = layoutInfo->FindElementWithCache(thread, nullptr, exportName.GetTaggedValue(), propertiesNumber); + if (idx != -1) { + return JSHandle::Cast(factory->NewResolvedIndexBindingRecord(module, idx)); + } + return thread->GlobalConstants()->GetHandledUndefined(); +} + JSHandle SourceTextModule::ResolveLocalExport(JSThread *thread, const JSHandle &exportEntry, const JSHandle &exportName, @@ -977,7 +1096,9 @@ JSHandle SourceTextModule::ResolveLocalExport(JSThread *thread, for (size_t idx = 0; idx < localExportEntriesLen; idx++) { ee.Update(localExportEntries->Get(idx)); // a. If SameValue(exportName, e.[[ExportName]]) is true, then - if (JSTaggedValue::SameValue(ee->GetExportName(), exportName.GetTaggedValue())) { + // if module == CommonJS, export first, check after execution. + if ((JSTaggedValue::SameValue(ee->GetExportName(), exportName.GetTaggedValue())) || + (module->GetTypes() == ModuleTypes::CJSMODULE)) { // Adapter new module if (module->GetIsNewBcVersion()) { return JSHandle::Cast(factory->NewResolvedIndexBindingRecord(module, idx)); diff --git a/ecmascript/module/js_module_source_text.h b/ecmascript/module/js_module_source_text.h index b438e6a23b..eb627f2292 100644 --- a/ecmascript/module/js_module_source_text.h +++ b/ecmascript/module/js_module_source_text.h @@ -47,7 +47,11 @@ public: static JSHandle ResolveExport(JSThread *thread, const JSHandle &module, const JSHandle &exportName, CVector, JSHandle>> &resolveSet); - + static JSHandle ResolveCjsExport(JSThread *thread, + const JSHandle &module, + const JSHandle &cjsModule, + const JSHandle &exportName, + CVector, JSHandle>> &resolveSet); // 15.2.1.16.4.1 InnerModuleInstantiation ( module, stack, index ) static int InnerModuleInstantiation(JSThread *thread, const JSHandle &moduleRecord, CVector> &stack, int index); @@ -110,6 +114,8 @@ public: const void *buffer = nullptr, size_t size = 0); // 15.2.1.16.4 Instantiate() + static void CJSInstantiate(JSThread *thread, const JSHandle &module, + const JSHandle &requiredModule); static int Instantiate(JSThread *thread, const JSHandle &module); JSTaggedValue GetModuleValue(JSThread *thread, int32_t index, bool isThrow); @@ -139,6 +145,13 @@ private: static JSHandle ResolveLocalExport(JSThread *thread, const JSHandle &exportEntry, const JSHandle &exportName, const JSHandle &module); + static JSHandle ResolveCjsLocalExport(JSThread *thread, + LayoutInfo *layoutInfo, + const JSHandle &exportName, + const JSHandle &module); + static bool CheckCircularImport(const JSHandle &module, + const JSHandle &exportName, + CVector, JSHandle>> &resolveSet); static void CheckResolvedBinding(JSThread *thread, const JSHandle &module); static void CheckResolvedIndexBinding(JSThread *thread, const JSHandle &module); static JSTaggedValue FindByExport(const JSTaggedValue &exportEntriesTv, const JSTaggedValue &key, diff --git a/ecmascript/require/js_cjs_module.cpp b/ecmascript/require/js_cjs_module.cpp index 7ef30bbcec..d4c60beed6 100644 --- a/ecmascript/require/js_cjs_module.cpp +++ b/ecmascript/require/js_cjs_module.cpp @@ -43,7 +43,6 @@ void CjsModule::InitializeModule(JSThread *thread, JSHandle &module, JSHandle CjsModule::SearchFromModuleCache(JSThread *thread, JSHandle &filename) { - [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); const GlobalEnvConstants *globalConst = thread->GlobalConstants(); @@ -56,7 +55,7 @@ JSHandle CjsModule::SearchFromModuleCache(JSThread *thread, JSHan JSHandle moduleCache = JSHandle(thread, modCache); if (moduleCache->ContainsModule(filename.GetTaggedValue())) { JSHandle cachedModule = JSHandle(thread, - moduleCache->GetModule(filename.GetTaggedValue())); + moduleCache->GetModule(filename.GetTaggedValue())); JSHandle exportsName = globalConst->GetHandledCjsExportsString(); JSTaggedValue cachedExports = SlowRuntimeStub::LdObjByName(thread, cachedModule.GetTaggedValue(), exportsName.GetTaggedValue(), diff --git a/test/moduletest/moduleUseCjs/BUILD.gn b/test/moduletest/moduleUseCjs/BUILD.gn index 1216082329..57b737d5cc 100644 --- a/test/moduletest/moduleUseCjs/BUILD.gn +++ b/test/moduletest/moduleUseCjs/BUILD.gn @@ -18,8 +18,16 @@ host_moduletest_action("Cjs") { is_commonjs = true } +host_moduletest_action("someArgsCjs") { + deps = [] + is_commonjs = true +} + host_moduletest_action("moduleUseCjs") { extra_modules = [ "Cjs" ] - deps = [ ":gen_Cjs_abc" ] + deps = [ + ":gen_Cjs_abc", + ":gen_someArgsCjs_abc", + ] is_module = true } diff --git a/test/moduletest/moduleUseCjs/expect_output.txt b/test/moduletest/moduleUseCjs/expect_output.txt index 2dcf09e379..8e91c96886 100644 --- a/test/moduletest/moduleUseCjs/expect_output.txt +++ b/test/moduletest/moduleUseCjs/expect_output.txt @@ -12,3 +12,6 @@ # limitations under the License. "module use cjsModule" +"moduleJson" +jscall 1 +true diff --git a/test/moduletest/moduleUseCjs/moduleUseCjs.js b/test/moduletest/moduleUseCjs/moduleUseCjs.js index 52fabb5218..e9b311cca1 100644 --- a/test/moduletest/moduleUseCjs/moduleUseCjs.js +++ b/test/moduletest/moduleUseCjs/moduleUseCjs.js @@ -20,4 +20,10 @@ * @tc.require: issueI5NO8G */ import cjs from "./Cjs" -print(JSON.stringify(cjs)) \ No newline at end of file +import * as ns from "./someArgsCjs" +import {json, fun} from "./someArgsCjs" + +print(JSON.stringify(cjs)); +print(JSON.stringify(json)); +fun(); +print(ns.tag); \ No newline at end of file diff --git a/test/moduletest/moduleUseCjs/someArgsCjs.js b/test/moduletest/moduleUseCjs/someArgsCjs.js new file mode 100644 index 0000000000..b4f0df210f --- /dev/null +++ b/test/moduletest/moduleUseCjs/someArgsCjs.js @@ -0,0 +1,26 @@ +/* + * 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. + */ + +/* + * @tc.name:moduleUseCjs + * @tc.desc:test module CJS + * @tc.type: FUNC + * @tc.require: issueI5NO8G + */ +module.exports.json = "moduleJson"; +module.exports.fun = function foo1 () { + print("jscall 1"); +}; +exports.tag = true; \ No newline at end of file From 8eeeb9fee347659182be801e36e1a5b9b94e5b74 Mon Sep 17 00:00:00 2001 From: zhaozhibo Date: Fri, 18 Nov 2022 17:48:50 +0800 Subject: [PATCH 02/14] add UT case for MathHelper Signed-off-by: zhaozhibo --- ecmascript/base/tests/BUILD.gn | 1 + ecmascript/base/tests/math_helper_test.cpp | 88 ++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 ecmascript/base/tests/math_helper_test.cpp diff --git a/ecmascript/base/tests/BUILD.gn b/ecmascript/base/tests/BUILD.gn index 361a52980f..7ff9dfce2f 100644 --- a/ecmascript/base/tests/BUILD.gn +++ b/ecmascript/base/tests/BUILD.gn @@ -28,6 +28,7 @@ host_unittest_action("BaseTest") { "gc_ring_buffer_test.cpp", "json_parser_test.cpp", "json_stringifier_test.cpp", + "math_helper_test.cpp", "number_helper_test.cpp", "string_helper_test.cpp", "typed_array_helper_test.cpp", diff --git a/ecmascript/base/tests/math_helper_test.cpp b/ecmascript/base/tests/math_helper_test.cpp new file mode 100644 index 0000000000..e8026b6705 --- /dev/null +++ b/ecmascript/base/tests/math_helper_test.cpp @@ -0,0 +1,88 @@ +/* + * 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/math_helper.h" +#include "ecmascript/tests/test_helper.h" + +using namespace panda::ecmascript; +using namespace panda::ecmascript::base; + +namespace panda::test { +class MathHelperTest : 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}; +}; + +HWTEST_F_L0(MathHelperTest, GetIntLog2_001) +{ + const uint32_t commonInput = static_cast(0b111111111) << 13; // 13 : left shift digit + const uint32_t maxInput = std::numeric_limits::max(); + EXPECT_EQ(MathHelper::GetIntLog2(commonInput), 13U); + EXPECT_EQ(MathHelper::GetIntLog2(maxInput), 0U); +} + +HWTEST_F_L0(MathHelperTest, GetIntLog2_002) +{ + const uint64_t commonInput = static_cast(0b111111111) << 53; // 53 : left shift digit + const uint64_t maxInput = std::numeric_limits::max(); + EXPECT_EQ(MathHelper::GetIntLog2(commonInput), 53U); + EXPECT_EQ(MathHelper::GetIntLog2(maxInput), 0U); +} + +HWTEST_F_L0(MathHelperTest, Asinh) +{ + EXPECT_EQ(MathHelper::Asinh(1), 0.88137358701954302523260932497979); + EXPECT_EQ(MathHelper::Asinh(+0), +0.0); + EXPECT_EQ(MathHelper::Asinh(-0), -0.0); + EXPECT_EQ(MathHelper::Asinh(-1), -0.88137358701954302523260932497979); + + double nanResult = MathHelper::Asinh(std::numeric_limits::signaling_NaN()); + EXPECT_TRUE(std::isnan(nanResult)); +} + +HWTEST_F_L0(MathHelperTest, Atanh) +{ + EXPECT_EQ(MathHelper::Atanh(0), 0); + EXPECT_EQ(MathHelper::Atanh(0.5), std::atanh(0.5)); + + double infResult = MathHelper::Atanh(-1); // limit value + EXPECT_TRUE(std::isinf(infResult)); + + double nanResult = MathHelper::Atanh(2); // out of input range + EXPECT_TRUE(std::isnan(nanResult)); +} +} // namespace panda::test From 6a73ef53963252ba53e6ef20697c756fc80f8207 Mon Sep 17 00:00:00 2001 From: zhaozhibo Date: Fri, 25 Nov 2022 11:03:12 +0800 Subject: [PATCH 03/14] add ut case for bitHelper Signed-off-by: zhaozhibo --- ecmascript/base/tests/BUILD.gn | 2 + ecmascript/base/tests/bit_helper_test.cpp | 112 ++++++++++++++++++ .../base/tests/file_path_helper_test.cpp | 69 +++++++++++ 3 files changed, 183 insertions(+) create mode 100644 ecmascript/base/tests/bit_helper_test.cpp create mode 100644 ecmascript/base/tests/file_path_helper_test.cpp diff --git a/ecmascript/base/tests/BUILD.gn b/ecmascript/base/tests/BUILD.gn index 361a52980f..6b8136c901 100644 --- a/ecmascript/base/tests/BUILD.gn +++ b/ecmascript/base/tests/BUILD.gn @@ -23,8 +23,10 @@ host_unittest_action("BaseTest") { # test file "array_helper_test.cpp", "atomic_helper_test.cpp", + "bit_helper_test.cpp", "builtins_base_test.cpp", "error_helper_test.cpp", + "file_path_helper_test.cpp", "gc_ring_buffer_test.cpp", "json_parser_test.cpp", "json_stringifier_test.cpp", diff --git a/ecmascript/base/tests/bit_helper_test.cpp b/ecmascript/base/tests/bit_helper_test.cpp new file mode 100644 index 0000000000..0fcb4dd57e --- /dev/null +++ b/ecmascript/base/tests/bit_helper_test.cpp @@ -0,0 +1,112 @@ +/* + * 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/bit_helper.h" +#include "ecmascript/tests/test_helper.h" + +using namespace panda::ecmascript; +using namespace panda::ecmascript::base; + +namespace panda::test { +class BitHelperTest : 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}; +}; + +HWTEST_F_L0(BitHelperTest, CountLeadingZeros_CountTrailingZeros) +{ + uint8_t uint8MaxValue = std::numeric_limits::max(); + uint8_t uint8MinValue = std::numeric_limits::min(); + EXPECT_EQ(CountLeadingZeros(uint8MaxValue), 0U); + EXPECT_EQ(CountLeadingZeros(uint8MinValue), 8U); + EXPECT_EQ(CountTrailingZeros(uint8MaxValue), 0U); + EXPECT_EQ(CountTrailingZeros(uint8MinValue), 8U); + + uint16_t uint16MaxValue = std::numeric_limits::max(); + uint16_t uint16MinValue = std::numeric_limits::min(); + EXPECT_EQ(CountLeadingZeros(uint16MaxValue), 0U); + EXPECT_EQ(CountLeadingZeros(uint16MinValue), 16U); + EXPECT_EQ(CountTrailingZeros(uint16MaxValue), 0U); + EXPECT_EQ(CountTrailingZeros(uint16MinValue), 16U); + + uint32_t uint32MaxValue = std::numeric_limits::max(); + uint32_t uint32MinValue = std::numeric_limits::min(); + EXPECT_EQ(CountLeadingZeros(uint32MaxValue), 0U); + EXPECT_EQ(CountLeadingZeros(uint32MinValue), 32U); + EXPECT_EQ(CountTrailingZeros(uint32MaxValue), 0U); + EXPECT_EQ(CountTrailingZeros(uint32MinValue), 32U); + + uint64_t uint64MaxValue = std::numeric_limits::max(); + uint64_t uint64MinValue = std::numeric_limits::min(); + EXPECT_EQ(CountLeadingZeros(uint64MaxValue), 0U); + EXPECT_EQ(CountLeadingZeros(uint64MinValue), 64U); + EXPECT_EQ(CountTrailingZeros(uint64MaxValue), 0U); + EXPECT_EQ(CountTrailingZeros(uint64MinValue), 64U); +} + +HWTEST_F_L0(BitHelperTest, CountLeadingZeros32_CountLeadingOnes32) +{ + uint32_t uint32MaxValue = std::numeric_limits::max(); + uint32_t uint32CommonValue1 = std::numeric_limits::max() >> 1; + uint32_t uint32CommonValue2 = std::numeric_limits::max() >> 31; // 31 : right shift digit + uint32_t uint32MinValue = std::numeric_limits::min(); + EXPECT_EQ(CountLeadingZeros32(uint32MaxValue), 0U); + EXPECT_EQ(CountLeadingZeros32(uint32CommonValue1), 1U); + EXPECT_EQ(CountLeadingZeros32(uint32CommonValue2), 31U); + EXPECT_EQ(CountLeadingZeros32(uint32MinValue), 32U); + EXPECT_EQ(CountLeadingOnes32(uint32MaxValue), 32U); + EXPECT_EQ(CountLeadingOnes32(uint32CommonValue1), 0U); + EXPECT_EQ(CountLeadingOnes32(uint32CommonValue2), 0U); + EXPECT_EQ(CountLeadingOnes32(uint32MinValue), 0U); +} + +HWTEST_F_L0(BitHelperTest, CountLeadingZeros64_CountLeadingOnes64) +{ + uint64_t uint64MaxValue = std::numeric_limits::max(); + uint64_t uint64CommonValue1 = std::numeric_limits::max() >> 1; + uint64_t uint64CommonValue2 = std::numeric_limits::max() >> 63; // 63 : right shift digit + uint64_t uint64MinValue = std::numeric_limits::min(); + EXPECT_EQ(CountLeadingZeros64(uint64MaxValue), 0U); + EXPECT_EQ(CountLeadingZeros64(uint64CommonValue1), 1U); + EXPECT_EQ(CountLeadingZeros64(uint64CommonValue2), 63U); + EXPECT_EQ(CountLeadingZeros64(uint64MinValue), 64U); + EXPECT_EQ(CountLeadingOnes64(uint64MaxValue), 64U); + EXPECT_EQ(CountLeadingOnes64(uint64CommonValue1), 0U); + EXPECT_EQ(CountLeadingOnes64(uint64CommonValue2), 0U); + EXPECT_EQ(CountLeadingOnes64(uint64MinValue), 0U); +} +} // namespace panda::test diff --git a/ecmascript/base/tests/file_path_helper_test.cpp b/ecmascript/base/tests/file_path_helper_test.cpp new file mode 100644 index 0000000000..fc28394ace --- /dev/null +++ b/ecmascript/base/tests/file_path_helper_test.cpp @@ -0,0 +1,69 @@ +/* + * 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/file_path_helper.h" +#include "ecmascript/tests/test_helper.h" + +using namespace panda::ecmascript; +using namespace panda::ecmascript::base; + +namespace panda::test { +class FilePathHelperTest : 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}; +}; + +HWTEST_F_L0(FilePathHelperTest, RealPath) +{ + std::string filePath = "__FilePathHelperTest.test"; + EXPECT_TRUE(std::fopen(filePath.c_str(), "r") == nullptr); + + std::string realPath; + bool result = FilePathHelper::RealPath(filePath, realPath, false); + EXPECT_EQ(result, true); + + std::fstream stream {}; + stream.open(realPath, std::ios::out); + EXPECT_EQ(stream.good(), true); + EXPECT_TRUE(std::fopen(realPath.c_str(), "r") != nullptr); + + stream.close(); + stream.clear(); + std::remove(filePath.c_str()); + std::remove(realPath.c_str()); +} +} // namespace panda::test From 6994c71849a319a05f09f03bb012f5448fb2c835 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Fri, 25 Nov 2022 14:44:53 +0800 Subject: [PATCH 04/14] deopt debug info In order to deopt debug, thus need add debug info, add bc print issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I634KP?from=project-issue Signed-off-by: songzhengchao Change-Id: Icd1487800045f39e4b46eb6d852da0e3d5e05d13 --- BUILD.gn | 2 +- ecmascript/aot_file_manager.h | 2 +- .../assembler/x64/extended_assembler_x64.cpp | 2 +- ecmascript/deoptimizer.cpp | 15 ++++++++++++--- ecmascript/deoptimizer.h | 6 +++++- ecmascript/{ => deoptimizer}/calleeReg.cpp | 3 ++- ecmascript/{ => deoptimizer}/calleeReg.h | 0 ecmascript/js_runtime_options.cpp | 10 ++++++++++ ecmascript/js_runtime_options.h | 12 ++++++++++++ 9 files changed, 44 insertions(+), 8 deletions(-) rename ecmascript/{ => deoptimizer}/calleeReg.cpp (95%) rename ecmascript/{ => deoptimizer}/calleeReg.h (100%) diff --git a/BUILD.gn b/BUILD.gn index 31e1b71059..8c3b8767f7 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -437,7 +437,6 @@ ecma_source = [ "ecmascript/builtins/builtins_weak_ref.cpp", "ecmascript/builtins/builtins_weak_set.cpp", "ecmascript/byte_array.cpp", - "ecmascript/calleeReg.cpp", "ecmascript/containers/containers_arraylist.cpp", "ecmascript/containers/containers_deque.cpp", "ecmascript/containers/containers_errors.cpp", @@ -454,6 +453,7 @@ ecma_source = [ "ecmascript/containers/containers_treemap.cpp", "ecmascript/containers/containers_treeset.cpp", "ecmascript/containers/containers_vector.cpp", + "ecmascript/deoptimizer/calleeReg.cpp", "ecmascript/dfx/pgo_profiler/pgo_profiler_loader.cpp", "ecmascript/dfx/pgo_profiler/pgo_profiler_manager.cpp", "ecmascript/dfx/stackinfo/js_stackinfo.cpp", diff --git a/ecmascript/aot_file_manager.h b/ecmascript/aot_file_manager.h index 674214529e..2fe7632268 100644 --- a/ecmascript/aot_file_manager.h +++ b/ecmascript/aot_file_manager.h @@ -16,7 +16,7 @@ #define ECMASCRIPT_AOT_FILE_MANAGER_H #include "ecmascript/ark_stackmap.h" -#include "ecmascript/calleeReg.h" +#include "ecmascript/deoptimizer/calleeReg.h" #include "ecmascript/js_function.h" #include "ecmascript/js_runtime_options.h" #include "ecmascript/compiler/binary_section.h" diff --git a/ecmascript/compiler/assembler/x64/extended_assembler_x64.cpp b/ecmascript/compiler/assembler/x64/extended_assembler_x64.cpp index 62b2e0e80d..a5613c74ef 100644 --- a/ecmascript/compiler/assembler/x64/extended_assembler_x64.cpp +++ b/ecmascript/compiler/assembler/x64/extended_assembler_x64.cpp @@ -14,7 +14,7 @@ */ #include "ecmascript/compiler/assembler/x64/extended_assembler_x64.h" -#include "ecmascript/calleeReg.h" +#include "ecmascript/deoptimizer/calleeReg.h" #include "ecmascript/frames.h" namespace panda::ecmascript::x64 { diff --git a/ecmascript/deoptimizer.cpp b/ecmascript/deoptimizer.cpp index 4a9d562df2..148ed62b23 100644 --- a/ecmascript/deoptimizer.cpp +++ b/ecmascript/deoptimizer.cpp @@ -227,13 +227,22 @@ bool Deoptimizier::CollectVirtualRegisters(Method* method, FrameWriter *frameWri return true; } +void Deoptimizier::Dump(Method* method) +{ + if (enableDeoptTrace_) { + std::string data = JsStackInfo::BuildMethodTrace(method, pc_); + LOG_COMPILER(INFO) << "Deoptimize" << data; + const uint8_t *pc = method->GetBytecodeArray() + pc_; + BytecodeInstruction inst(pc); + LOG_COMPILER(INFO) << inst; + } +} + JSTaggedType Deoptimizier::ConstructAsmInterpretFrame() { JSTaggedValue callTarget = GetFrameArgv(kungfu::CommonArgIdx::FUNC); auto method = GetMethod(callTarget); - std::string data = JsStackInfo::BuildMethodTrace(method, pc_); - - LOG_COMPILER(DEBUG) << "Deoptimize" << data; + Dump(method); ASSERT(thread_ != nullptr); FrameWriter frameWriter(this); diff --git a/ecmascript/deoptimizer.h b/ecmascript/deoptimizer.h index 8af2b788dd..aca3a6be8d 100644 --- a/ecmascript/deoptimizer.h +++ b/ecmascript/deoptimizer.h @@ -16,8 +16,8 @@ #ifndef ECMASCRIPT_DEOPTIMIZER_H #define ECMASCRIPT_DEOPTIMIZER_H #include "ecmascript/base/aligned_struct.h" -#include "ecmascript/calleeReg.h" #include "ecmascript/compiler/argument_accessor.h" +#include "ecmascript/deoptimizer/calleeReg.h" #include "ecmascript/js_handle.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/llvm_stackmap_type.h" @@ -92,6 +92,8 @@ public: { kungfu::CalleeReg callreg; numCalleeRegs_ = static_cast(callreg.GetCallRegNum()); + JSRuntimeOptions options = thread_->GetEcmaVM()->GetJSOptions(); + enableDeoptTrace_ = options.IsEnableDeoptTrace(); } void CollectVregs(const std::vector& deoptBundle); void CollectDeoptBundleVec(std::vector& deoptBundle); @@ -136,6 +138,7 @@ private: } Method* GetMethod(JSTaggedValue &target); void RelocateCalleeSave(); + void Dump(Method* method); JSThread *thread_ {nullptr}; uintptr_t *calleeRegAddr_ {nullptr}; size_t numCalleeRegs_ {0}; @@ -147,6 +150,7 @@ private: JSTaggedValue env_ {JSTaggedValue::Undefined()}; size_t frameArgc_ {0}; JSTaggedType *frameArgvs_ {nullptr}; + bool enableDeoptTrace_ {false}; }; } // namespace panda::ecmascript diff --git a/ecmascript/calleeReg.cpp b/ecmascript/deoptimizer/calleeReg.cpp similarity index 95% rename from ecmascript/calleeReg.cpp rename to ecmascript/deoptimizer/calleeReg.cpp index 9e0c070370..d1efca02cf 100644 --- a/ecmascript/calleeReg.cpp +++ b/ecmascript/deoptimizer/calleeReg.cpp @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "ecmascript/calleeReg.h" +#include "ecmascript/deoptimizer/calleeReg.h" #include "libpandabase/macros.h" #include @@ -58,6 +58,7 @@ int CalleeReg::FindCallRegOrder(const DwarfRegType reg) const if (it != reg2Location_.end()) { return it->second; } else { + LOG_FULL(FATAL) << "reg:" << std::dec << reg; UNREACHABLE(); } } diff --git a/ecmascript/calleeReg.h b/ecmascript/deoptimizer/calleeReg.h similarity index 100% rename from ecmascript/calleeReg.h rename to ecmascript/deoptimizer/calleeReg.h diff --git a/ecmascript/js_runtime_options.cpp b/ecmascript/js_runtime_options.cpp index 54ad472e8e..cb684e074e 100644 --- a/ecmascript/js_runtime_options.cpp +++ b/ecmascript/js_runtime_options.cpp @@ -57,6 +57,7 @@ const std::string PUBLIC_API HELP_OPTION_MSG = "--compiler-log-time: Enable to print pass compiler time. Default: false\n" "--enable-ark-tools: Enable ark tools to debug. Default: false\n" "--enable-bytecode-trace: enable tracing bytecode for aot runtime. Default: false\n" + "--enable-deopt-trace: enable tracing deopt for aot runtime. Default: false\n" "--enable-cpuprofiler: Enable cpuprofiler to sample call stack and output to json file. Default: false\n" "--enable-force-gc: enable force gc when allocating object. Default: true\n" "--enable-ic: switch of inline cache. Default: true\n" @@ -124,6 +125,7 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv) {"compiler-log-time", required_argument, nullptr, OPTION_COMPILER_LOG_TIME}, {"enable-ark-tools", required_argument, nullptr, OPTION_ENABLE_ARK_TOOLS}, {"enable-bytecode-trace", required_argument, nullptr, OPTION_ENABLE_BC_TRACE}, + {"enable-deopt-trace", required_argument, nullptr, OPTION_ENABLE_DEOPT_TRACE}, {"enable-cpuprofiler", required_argument, nullptr, OPTION_ENABLE_CPUPROFILER}, {"enable-force-gc", required_argument, nullptr, OPTION_ENABLE_FORCE_GC}, {"enable-ic", required_argument, nullptr, OPTION_ENABLE_IC}, @@ -270,6 +272,14 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv) return false; } break; + case OPTION_ENABLE_DEOPT_TRACE: + ret = ParseBoolParam(&argBool); + if (ret) { + SetEnableDeoptTrace(argBool); + } else { + return false; + } + break; case OPTION_ENABLE_CPUPROFILER: ret = ParseBoolParam(&argBool); if (ret) { diff --git a/ecmascript/js_runtime_options.h b/ecmascript/js_runtime_options.h index c00a2b3833..658f01f2fa 100644 --- a/ecmascript/js_runtime_options.h +++ b/ecmascript/js_runtime_options.h @@ -87,6 +87,7 @@ enum CommandValues { OPTION_IS_WORKER, OPTION_BUILTINS_DTS, OPTION_ENABLE_BC_TRACE, + OPTION_ENABLE_DEOPT_TRACE, OPTION_LOG_LEVEL, OPTION_LOG_DEBUG, OPTION_LOG_INFO, @@ -810,6 +811,16 @@ public: { wasSet_ |= 1ULL << static_cast(opt); } + + void SetEnableDeoptTrace(bool value) + { + enableDeoptTrace_ = value; + } + + bool IsEnableDeoptTrace() const + { + return enableDeoptTrace_; + } private: static bool StartsWith(const std::string &haystack, const std::string &needle) { @@ -877,6 +888,7 @@ private: bool enablePGOProfiler_ {false}; uint32_t pgoHotnessThreshold_ {2}; std::string pgoProfilerPath_ {""}; + bool enableDeoptTrace_ {false}; }; } // namespace panda::ecmascript From 1d29a3a8250f7774dba8fc632349ca91e6590d06 Mon Sep 17 00:00:00 2001 From: wanghuan Date: Sun, 23 Oct 2022 23:17:44 +0800 Subject: [PATCH 05/14] add TreeString and LineString desc: add TreeString and LineString solu: 1. add TreeString and LineString 2. all string fucntions fit new construction Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I5X82Y Signed-off-by: wanghuan Change-Id: I6c6ded38ee67741b5c0f17f19b72e68a4375b303 --- ecmascript/base/json_stringifier.cpp | 8 +- ecmascript/base/number_helper.cpp | 2 +- .../base/tests/json_stringifier_test.cpp | 2 +- ecmascript/base/tests/number_helper_test.cpp | 64 +- ecmascript/builtins/builtins.cpp | 12 +- ecmascript/builtins/builtins_date.cpp | 7 +- ecmascript/builtins/builtins_number.cpp | 4 +- ecmascript/builtins/builtins_promise_job.cpp | 4 +- ecmascript/builtins/builtins_regexp.cpp | 8 +- ecmascript/builtins/builtins_string.cpp | 89 +-- ecmascript/builtins/builtins_typedarray.cpp | 2 +- .../builtins/tests/builtins_array_test.cpp | 6 +- .../builtins/tests/builtins_bigint_test.cpp | 24 +- .../builtins/tests/builtins_boolean_test.cpp | 4 +- .../builtins/tests/builtins_collator_test.cpp | 2 +- .../tests/builtins_date_time_format_test.cpp | 4 +- .../builtins/tests/builtins_errors_test.cpp | 260 +++---- .../builtins/tests/builtins_function_test.cpp | 10 +- .../builtins/tests/builtins_locale_test.cpp | 2 +- .../builtins/tests/builtins_number_test.cpp | 55 +- .../builtins/tests/builtins_object_test.cpp | 20 +- .../builtins/tests/builtins_reflect_test.cpp | 15 +- .../builtins/tests/builtins_regexp_test.cpp | 58 +- .../builtins/tests/builtins_string_test.cpp | 73 +- .../builtins/tests/builtins_symbol_test.cpp | 10 +- .../builtins/builtins_string_stub_builder.cpp | 36 +- .../builtins/builtins_string_stub_builder.h | 2 +- ecmascript/compiler/circuit_builder-inl.h | 10 +- ecmascript/compiler/circuit_builder.cpp | 32 +- ecmascript/compiler/circuit_builder.h | 2 + ecmascript/compiler/common_stubs.cpp | 2 +- ecmascript/compiler/ic_stub_builder.cpp | 2 +- .../compiler/new_object_stub_builder.cpp | 8 +- ecmascript/compiler/new_object_stub_builder.h | 2 +- ecmascript/compiler/slowpath_lowering.cpp | 16 +- ecmascript/compiler/stub_builder-inl.h | 41 +- ecmascript/compiler/stub_builder.cpp | 139 ++-- ecmascript/compiler/stub_builder.h | 15 +- .../tests/containers_treemap_test.cpp | 6 +- .../tests/containers_treeset_test.cpp | 6 +- ecmascript/dfx/hprof/heap_snapshot.cpp | 7 +- ecmascript/dump.cpp | 11 +- ecmascript/ecma_string-inl.h | 354 +++++++-- ecmascript/ecma_string.cpp | 502 +++++++++---- ecmascript/ecma_string.h | 674 +++++++++++------- ecmascript/ecma_string_table.cpp | 27 +- ecmascript/global_env_constants.cpp | 3 +- ecmascript/global_env_constants.h | 3 +- ecmascript/ic/ic_compare_op.cpp | 6 +- ecmascript/ic/tests/ic_binaryop_test.cpp | 8 +- .../interpreter/fast_runtime_stub-inl.h | 28 +- ecmascript/interpreter/fast_runtime_stub.h | 2 +- ecmascript/interpreter/interpreter-inl.h | 25 +- .../interpreter/interpreter_assembly.cpp | 23 +- ecmascript/js_hclass-inl.h | 5 +- ecmascript/js_hclass.h | 24 +- ecmascript/js_locale.cpp | 4 +- ecmascript/js_primitive_ref.cpp | 10 +- ecmascript/js_serializer.cpp | 6 +- ecmascript/js_stable_array.cpp | 2 +- ecmascript/js_tagged_value-inl.h | 12 +- ecmascript/js_tagged_value.cpp | 13 +- ecmascript/js_tagged_value.h | 2 + ecmascript/mem/object_xray.h | 5 +- ecmascript/napi/include/jsnapi.h | 2 +- ecmascript/napi/jsnapi.cpp | 5 +- ecmascript/napi/test/jsnapi_tests.cpp | 8 +- ecmascript/object_factory-inl.h | 19 +- ecmascript/object_factory.h | 8 +- ecmascript/regexp/tests/regexp_test.cpp | 174 ++--- .../snapshot/mem/snapshot_processor.cpp | 24 +- ecmascript/snapshot/tests/snapshot_test.cpp | 17 +- ecmascript/stubs/runtime_stubs-inl.h | 16 +- ecmascript/stubs/runtime_stubs.cpp | 18 +- ecmascript/stubs/runtime_stubs.h | 3 +- ecmascript/tagged_tree.h | 6 +- ecmascript/tests/dump_test.cpp | 3 +- .../tests/ecma_string_accessor_test.cpp | 233 +++--- ecmascript/tests/ecma_string_test.cpp | 126 +--- .../tests/js_api_lightweightset_test.cpp | 7 +- ecmascript/tests/js_api_plain_array_test.cpp | 6 +- ecmascript/tests/js_handle_test.cpp | 36 +- ecmascript/tests/js_hclass_test.cpp | 19 +- ecmascript/tests/js_locale_test.cpp | 2 +- ecmascript/tests/js_primitive_ref_test.cpp | 2 +- ecmascript/tests/js_regexp_iterator_test.cpp | 2 +- ecmascript/tests/tagged_tree_test.cpp | 6 +- ecmascript/tests/tagged_value_test.cpp | 8 +- 88 files changed, 2165 insertions(+), 1405 deletions(-) diff --git a/ecmascript/base/json_stringifier.cpp b/ecmascript/base/json_stringifier.cpp index fa9297ab5e..167ba6f8d2 100644 --- a/ecmascript/base/json_stringifier.cpp +++ b/ecmascript/base/json_stringifier.cpp @@ -366,8 +366,12 @@ JSTaggedValue JsonStringifier::SerializeJSONProperty(const JSHandle(valHandle), StringConvertedUsage::LOGICOPERATION); + case JSType::LINE_STRING: + case JSType::TREE_STRING: { + JSHandle strHandle = JSHandle(valHandle); + auto string = JSHandle(thread_, + EcmaStringAccessor::Flatten(thread_->GetEcmaVM(), strHandle)); + CString str = ConvertToString(*string, StringConvertedUsage::LOGICOPERATION); str = ValueToQuotedString(str); result_ += str; return tagValue; diff --git a/ecmascript/base/number_helper.cpp b/ecmascript/base/number_helper.cpp index a69ad3ae55..a9dd3ce349 100644 --- a/ecmascript/base/number_helper.cpp +++ b/ecmascript/base/number_helper.cpp @@ -687,7 +687,7 @@ JSTaggedValue NumberHelper::StringToBigInt(JSThread *thread, JSHandle buf; + CVector buf; Span str = EcmaStringAccessor(strObj).ToUtf8Span(buf); auto p = const_cast(str.begin()); diff --git a/ecmascript/base/tests/json_stringifier_test.cpp b/ecmascript/base/tests/json_stringifier_test.cpp index 7fd7a91477..66502eaf3a 100644 --- a/ecmascript/base/tests/json_stringifier_test.cpp +++ b/ecmascript/base/tests/json_stringifier_test.cpp @@ -171,7 +171,7 @@ HWTEST_F_L0(JsonStringifierTest, Stringify_003) EXPECT_TRUE(resultString->IsString()); JSHandle resultStr = factory->NewFromASCII("{\ntttt\"z\": 1,\ntttt\"x\": 3.6,\ntttt\"y\": \"abc\"\n}"); - EXPECT_EQ(EcmaStringAccessor::Compare(*resultStr, reinterpret_cast(resultString->GetRawData())), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultStr, JSHandle(resultString)), 0); } /** diff --git a/ecmascript/base/tests/number_helper_test.cpp b/ecmascript/base/tests/number_helper_test.cpp index 67087dfc28..8dd90e4a04 100644 --- a/ecmascript/base/tests/number_helper_test.cpp +++ b/ecmascript/base/tests/number_helper_test.cpp @@ -86,37 +86,37 @@ HWTEST_F_L0(NumberHelperTest, DoubleToString_001) radix = 2; JSHandle resultStr = factory->NewFromASCII("100101"); JSHandle handleEcmaStr1(thread, NumberHelper::DoubleToString(thread, 37, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr1, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr1, resultStr), 0); radix = 3; resultStr = factory->NewFromASCII("-1101"); JSHandle handleEcmaStr2(thread, NumberHelper::DoubleToString(thread, -37, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr2, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr2, resultStr), 0); radix = 4; resultStr = factory->NewFromASCII("211"); JSHandle handleEcmaStr3(thread, NumberHelper::DoubleToString(thread, 37, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr3, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr3, resultStr), 0); radix = 5; resultStr = factory->NewFromASCII("122"); JSHandle handleEcmaStr4(thread, NumberHelper::DoubleToString(thread, 37, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr4, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr4, resultStr), 0); radix = 6; resultStr = factory->NewFromASCII("101"); JSHandle handleEcmaStr6(thread, NumberHelper::DoubleToString(thread, 37, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr6, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr6, resultStr), 0); radix = 7; resultStr = factory->NewFromASCII("52"); JSHandle handleEcmaStr7(thread, NumberHelper::DoubleToString(thread, 37, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr7, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr7, resultStr), 0); radix = 36; resultStr = factory->NewFromASCII("11"); JSHandle handleEcmaStr5(thread, NumberHelper::DoubleToString(thread, 37, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr5, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr5, resultStr), 0); } HWTEST_F_L0(NumberHelperTest, DoubleToString_002) @@ -127,28 +127,28 @@ HWTEST_F_L0(NumberHelperTest, DoubleToString_002) JSHandle resultStr = factory->NewFromASCII("10.111111011011000110000101010010001010100110111101"); JSHandle handleEcmaStr1(thread, NumberHelper::DoubleToString(thread, 2.99099, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr1, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr1, resultStr), 0); resultStr = factory->NewFromASCII("10.000000101001000000000011111011101010001000001001101"); JSHandle handleEcmaStr2(thread, NumberHelper::DoubleToString(thread, 2.01001, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr2, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr2, resultStr), 0); resultStr = factory->NewFromASCII("10.100000000000011010001101101110001011101011000111001"); JSHandle handleEcmaStr3(thread, NumberHelper::DoubleToString(thread, 2.5001, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr3, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr3, resultStr), 0); radix = 36; resultStr = factory->NewFromASCII("0.i04nym8equ"); JSHandle handleEcmaStr4(thread, NumberHelper::DoubleToString(thread, 0.5001, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr4, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr4, resultStr), 0); resultStr = factory->NewFromASCII("0.wej2d0mt58f"); JSHandle handleEcmaStr5(thread, NumberHelper::DoubleToString(thread, 0.9001, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr5, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr5, resultStr), 0); resultStr = factory->NewFromASCII("0.0d384dldb02"); JSHandle handleEcmaStr6(thread, NumberHelper::DoubleToString(thread, 0.0101, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr6, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr6, resultStr), 0); } /** @@ -313,32 +313,32 @@ HWTEST_F_L0(NumberHelperTest, DoubleToExponential) radix = -4; JSHandle resultStr = factory->NewFromASCII("1.239876e+2"); JSHandle handleEcmaStr1(thread, NumberHelper::DoubleToExponential(thread, 123.9876, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr1, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr1, resultStr), 0); radix = -6; resultStr = factory->NewFromASCII("1.239876e+2"); JSHandle handleEcmaStr2(thread, NumberHelper::DoubleToExponential(thread, 123.9876, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr2, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr2, resultStr), 0); radix = 2; resultStr = factory->NewFromASCII("1.24e+2"); JSHandle handleEcmaStr3(thread, NumberHelper::DoubleToExponential(thread, 123.567, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr3, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr3, resultStr), 0); radix = 6; resultStr = factory->NewFromASCII("1.234567e+2"); JSHandle handleEcmaStr4(thread, NumberHelper::DoubleToExponential(thread, 123.4567, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr4, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr4, resultStr), 0); radix = 7; resultStr = factory->NewFromASCII("1.2345670e+2"); JSHandle handleEcmaStr5(thread, NumberHelper::DoubleToExponential(thread, 123.45670, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr5, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr5, resultStr), 0); radix = 3; resultStr = factory->NewFromASCII("1.230e+2"); JSHandle handleEcmaStr6(thread, NumberHelper::DoubleToExponential(thread, 123.0123, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr6, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr6, resultStr), 0); } HWTEST_F_L0(NumberHelperTest, DoubleToFixed) @@ -349,27 +349,27 @@ HWTEST_F_L0(NumberHelperTest, DoubleToFixed) radix = 1; JSHandle resultStr = factory->NewFromASCII("123.5"); JSHandle handleEcmaStr1(thread, NumberHelper::DoubleToFixed(thread, 123.456, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr1, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr1, resultStr), 0); radix = 2; resultStr = factory->NewFromASCII("123.46"); JSHandle handleEcmaStr2(thread, NumberHelper::DoubleToFixed(thread, 123.456, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr2, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr2, resultStr), 0); radix = 3; resultStr = factory->NewFromASCII("123.456"); JSHandle handleEcmaStr3(thread, NumberHelper::DoubleToFixed(thread, 123.456, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr3, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr3, resultStr), 0); radix = 4; resultStr = factory->NewFromASCII("123.4560"); JSHandle handleEcmaStr4(thread, NumberHelper::DoubleToFixed(thread, 123.456, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr4, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr4, resultStr), 0); radix = 0; resultStr = factory->NewFromASCII("123"); JSHandle handleEcmaStr5(thread, NumberHelper::DoubleToFixed(thread, 123.456, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr5, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr5, resultStr), 0); } /** @@ -389,24 +389,24 @@ HWTEST_F_L0(NumberHelperTest, DoubleToPrecision) radix = 1; JSHandle resultStr = factory->NewFromASCII("0"); JSHandle handleEcmaStr1(thread, NumberHelper::DoubleToPrecision(thread, 0.0, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr1, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr1, resultStr), 0); resultStr = factory->NewFromASCII("0.0001"); JSHandle handleEcmaStr2(thread, NumberHelper::DoubleToPrecision(thread, 0.0001, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr2, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr2, resultStr), 0); resultStr = factory->NewFromASCII("1e-7"); JSHandle handleEcmaStr3(thread, NumberHelper::DoubleToPrecision(thread, 0.0000001, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr3, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr3, resultStr), 0); resultStr = factory->NewFromASCII("1e+3"); JSHandle handleEcmaStr5(thread, NumberHelper::DoubleToPrecision(thread, 1000.1234, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr5, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr5, resultStr), 0); radix = 6; resultStr = factory->NewFromASCII("1000.12"); JSHandle handleEcmaStr6(thread, NumberHelper::DoubleToPrecision(thread, 1000.1234, radix)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr6, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr6, resultStr), 0); } /** @@ -423,7 +423,7 @@ HWTEST_F_L0(NumberHelperTest, StringToDoubleWithRadix) ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); int radix; Span sp; - [[maybe_unused]] CVector buf; + CVector buf; JSHandle resultStr; radix = 3; @@ -530,11 +530,11 @@ HWTEST_F_L0(NumberHelperTest, NumberToString) double d = 8.1999999999999993; JSHandle result = NumberHelper::NumberToString(thread, JSTaggedValue(d)); JSHandle target = factory->NewFromASCII("8.2"); - EXPECT_EQ(EcmaStringAccessor::Compare(*result, *target), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, result, target), 0); double d2 = 0.30000000000000004; JSHandle result1 = NumberHelper::NumberToString(thread, JSTaggedValue(d2)); JSHandle target1 = factory->NewFromASCII("0.30000000000000004"); - EXPECT_EQ(EcmaStringAccessor::Compare(*result1, *target1), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, result1, target1), 0); } } // namespace panda::ecmascript \ No newline at end of file diff --git a/ecmascript/builtins/builtins.cpp b/ecmascript/builtins/builtins.cpp index e2af71eca2..39af8ffe06 100644 --- a/ecmascript/builtins/builtins.cpp +++ b/ecmascript/builtins/builtins.cpp @@ -1593,16 +1593,13 @@ void Builtins::InitializeString(const JSHandle &env, const JSHandle()->SetFunctionPrototype(thread_, stringFuncInstanceHClass.GetTaggedValue()); // String.prototype method - SetFunction(env, stringFuncPrototype, "charAt", BuiltinsString::CharAt, FunctionLength::ONE, - static_cast(BUILTINS_STUB_ID(CharAt))); - SetFunction(env, stringFuncPrototype, "charCodeAt", BuiltinsString::CharCodeAt, FunctionLength::ONE, - static_cast(BUILTINS_STUB_ID(CharCodeAt))); + SetFunction(env, stringFuncPrototype, "charAt", BuiltinsString::CharAt, FunctionLength::ONE); + SetFunction(env, stringFuncPrototype, "charCodeAt", BuiltinsString::CharCodeAt, FunctionLength::ONE); SetFunction(env, stringFuncPrototype, "codePointAt", BuiltinsString::CodePointAt, FunctionLength::ONE); SetFunction(env, stringFuncPrototype, "concat", BuiltinsString::Concat, FunctionLength::ONE); SetFunction(env, stringFuncPrototype, "endsWith", BuiltinsString::EndsWith, FunctionLength::ONE); SetFunction(env, stringFuncPrototype, "includes", BuiltinsString::Includes, FunctionLength::ONE); - SetFunction(env, stringFuncPrototype, "indexOf", BuiltinsString::IndexOf, FunctionLength::ONE, - static_cast(BUILTINS_STUB_ID(IndexOf))); + SetFunction(env, stringFuncPrototype, "indexOf", BuiltinsString::IndexOf, FunctionLength::ONE); SetFunction(env, stringFuncPrototype, "lastIndexOf", BuiltinsString::LastIndexOf, FunctionLength::ONE); SetFunction(env, stringFuncPrototype, "localeCompare", BuiltinsString::LocaleCompare, FunctionLength::ONE); SetFunction(env, stringFuncPrototype, "match", BuiltinsString::Match, FunctionLength::ONE); @@ -1617,8 +1614,7 @@ void Builtins::InitializeString(const JSHandle &env, const JSHandle(BUILTINS_STUB_ID(Substring))); + SetFunction(env, stringFuncPrototype, "substring", BuiltinsString::Substring, FunctionLength::TWO); SetFunction(env, stringFuncPrototype, "substr", BuiltinsString::SubStr, FunctionLength::TWO); SetFunction(env, stringFuncPrototype, "toLocaleLowerCase", BuiltinsString::ToLocaleLowerCase, FunctionLength::ZERO); SetFunction(env, stringFuncPrototype, "toLocaleUpperCase", BuiltinsString::ToLocaleUpperCase, FunctionLength::ZERO); diff --git a/ecmascript/builtins/builtins_date.cpp b/ecmascript/builtins/builtins_date.cpp index e911127594..4ee395ece5 100644 --- a/ecmascript/builtins/builtins_date.cpp +++ b/ecmascript/builtins/builtins_date.cpp @@ -203,6 +203,7 @@ JSTaggedValue BuiltinsDate::ToPrimitive(EcmaRuntimeCallInfo *argv) ASSERT(argv); BUILTINS_API_TRACE(argv->GetThread(), Date, ToPrimitive); JSThread *thread = argv->GetThread(); + auto vm = thread->GetEcmaVM(); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle object = GetThis(argv); @@ -214,13 +215,13 @@ JSTaggedValue BuiltinsDate::ToPrimitive(EcmaRuntimeCallInfo *argv) const GlobalEnvConstants *globalConst = thread->GlobalConstants(); if (hint->IsString()) { JSHandle numberStrHandle = JSHandle::Cast(globalConst->GetHandledNumberString()); - if (EcmaStringAccessor::StringsAreEqual(hint.GetObject(), *numberStrHandle)) { + if (EcmaStringAccessor::StringsAreEqual(vm, JSHandle(hint), numberStrHandle)) { tryFirst = PREFER_NUMBER; } else { JSHandle stringStrHandle = JSHandle::Cast(globalConst->GetHandledStringString()); JSHandle defaultStrHandle = JSHandle::Cast(globalConst->GetHandledDefaultString()); - if (EcmaStringAccessor::StringsAreEqual(hint.GetObject(), *stringStrHandle) || - EcmaStringAccessor::StringsAreEqual(hint.GetObject(), *defaultStrHandle)) { + if (EcmaStringAccessor::StringsAreEqual(vm, JSHandle(hint), stringStrHandle) || + EcmaStringAccessor::StringsAreEqual(vm, JSHandle(hint), defaultStrHandle)) { tryFirst = PREFER_STRING; } else { THROW_TYPE_ERROR_AND_RETURN(thread, "This is not a primitiveType.", JSTaggedValue::Exception()); diff --git a/ecmascript/builtins/builtins_number.cpp b/ecmascript/builtins/builtins_number.cpp index d3cd78a119..4d6fc53d8e 100644 --- a/ecmascript/builtins/builtins_number.cpp +++ b/ecmascript/builtins/builtins_number.cpp @@ -159,7 +159,7 @@ JSTaggedValue BuiltinsNumber::ParseFloat(EcmaRuntimeCallInfo *argv) JSHandle numberString = JSTaggedValue::ToString(thread, msg); // 2. ReturnIfAbrupt(inputString). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - [[maybe_unused]] CVector buf; + CVector buf; Span str = EcmaStringAccessor(numberString).ToUtf8Span(buf); // 4. If neither trimmedString nor any prefix of trimmedString satisfies the syntax of a StrDecimalLiteral // (see 7.1.3.1), return NaN. @@ -190,7 +190,7 @@ JSTaggedValue BuiltinsNumber::ParseInt(EcmaRuntimeCallInfo *argv) // 1. Let inputString be ToString(string). JSHandle numberString = JSTaggedValue::ToString(thread, msg); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - [[maybe_unused]] CVector buf; + CVector buf; Span str = EcmaStringAccessor(numberString).ToUtf8Span(buf); JSTaggedValue result = NumberHelper::StringToDoubleWithRadix(str.begin(), str.end(), radix); diff --git a/ecmascript/builtins/builtins_promise_job.cpp b/ecmascript/builtins/builtins_promise_job.cpp index 511ad8a6c5..b0ec5d5ec8 100644 --- a/ecmascript/builtins/builtins_promise_job.cpp +++ b/ecmascript/builtins/builtins_promise_job.cpp @@ -54,8 +54,8 @@ JSTaggedValue BuiltinsPromiseJob::PromiseReactionJob(EcmaRuntimeCallInfo *argv) // 5. Else if handler is "Thrower", let handlerResult be Completion{[[type]]: throw, [[value]]: argument, // [[target]]: empty}. - if (EcmaStringAccessor::StringsAreEqual(handler.GetObject(), - globalConst->GetHandledThrowerString().GetObject())) { + if (EcmaStringAccessor::StringsAreEqual(thread->GetEcmaVM(), + JSHandle(handler), JSHandle(globalConst->GetHandledThrowerString()))) { call.Update(capability->GetReject()); } } else { diff --git a/ecmascript/builtins/builtins_regexp.cpp b/ecmascript/builtins/builtins_regexp.cpp index 1d03c53a1b..69b0331827 100644 --- a/ecmascript/builtins/builtins_regexp.cpp +++ b/ecmascript/builtins/builtins_regexp.cpp @@ -553,7 +553,7 @@ JSTaggedValue BuiltinsRegExp::MatchAll(EcmaRuntimeCallInfo *argv) // 10. Else, let global be false. JSHandle gString(globalConstants->GetHandledGString()); bool global = false; - if (EcmaStringAccessor::IndexOf(*flagsStrHandle, *gString) != -1) { + if (EcmaStringAccessor::IndexOf(ecmaVm, flagsStrHandle, gString) != -1) { global = true; } @@ -561,7 +561,7 @@ JSTaggedValue BuiltinsRegExp::MatchAll(EcmaRuntimeCallInfo *argv) // 12. Else, let fullUnicode be false. JSHandle uString(globalConstants->GetHandledUString()); bool fullUnicode = false; - if (EcmaStringAccessor::IndexOf(*flagsStrHandle, *uString) != -1) { + if (EcmaStringAccessor::IndexOf(ecmaVm, flagsStrHandle, uString) != -1) { fullUnicode = true; } @@ -1106,11 +1106,11 @@ JSTaggedValue BuiltinsRegExp::Split(EcmaRuntimeCallInfo *argv) // 9. If flags contains "u", let unicodeMatching be true. // 10. Else, let unicodeMatching be false. JSHandle uStringHandle(globalConstants->GetHandledUString()); - bool unicodeMatching = (EcmaStringAccessor::IndexOf(*flags, *uStringHandle) != -1); + bool unicodeMatching = (EcmaStringAccessor::IndexOf(ecmaVm, flags, uStringHandle) != -1); // 11. If flags contains "y", let newFlags be flags. JSHandle newFlagsHandle; JSHandle yStringHandle = JSHandle::Cast(globalConstants->GetHandledYString()); - if (EcmaStringAccessor::IndexOf(*flags, *yStringHandle) != -1) { + if (EcmaStringAccessor::IndexOf(ecmaVm, flags, yStringHandle) != -1) { newFlagsHandle = flags; } else { // 12. Else, let newFlags be the string that is the concatenation of flags and "y". diff --git a/ecmascript/builtins/builtins_string.cpp b/ecmascript/builtins/builtins_string.cpp index 2c27f4f3f3..70050aeeb9 100644 --- a/ecmascript/builtins/builtins_string.cpp +++ b/ecmascript/builtins/builtins_string.cpp @@ -242,7 +242,9 @@ JSTaggedValue BuiltinsString::CharAt(EcmaRuntimeCallInfo *argv) JSHandle thisTag(JSTaggedValue::RequireObjectCoercible(thread, GetThis(argv))); JSHandle thisHandle = JSTaggedValue::ToString(thread, thisTag); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - int32_t thisLen = static_cast(EcmaStringAccessor(thisHandle).GetLength()); + JSHandle thisFlat = JSHandle(thread, + EcmaStringAccessor::Flatten(thread->GetEcmaVM(), thisHandle)); + int32_t thisLen = static_cast(EcmaStringAccessor(thisFlat).GetLength()); JSHandle posTag = BuiltinsString::GetCallArg(argv, 0); int32_t pos; if (posTag->IsInt()) { @@ -257,7 +259,7 @@ JSTaggedValue BuiltinsString::CharAt(EcmaRuntimeCallInfo *argv) if (pos < 0 || pos >= thisLen) { return factory->GetEmptyString().GetTaggedValue(); } - uint16_t res = EcmaStringAccessor(thisHandle).Get(pos); + uint16_t res = EcmaStringAccessor(thisFlat).Get(pos); return factory->NewFromUtf16Literal(&res, 1).GetTaggedValue(); } @@ -271,7 +273,9 @@ JSTaggedValue BuiltinsString::CharCodeAt(EcmaRuntimeCallInfo *argv) JSHandle thisTag(JSTaggedValue::RequireObjectCoercible(thread, GetThis(argv))); JSHandle thisHandle = JSTaggedValue::ToString(thread, thisTag); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - int32_t thisLen = static_cast(EcmaStringAccessor(thisHandle).GetLength()); + JSHandle thisFlat = JSHandle(thread, + EcmaStringAccessor::Flatten(thread->GetEcmaVM(), thisHandle)); + int32_t thisLen = static_cast(EcmaStringAccessor(thisFlat).GetLength()); JSHandle posTag = BuiltinsString::GetCallArg(argv, 0); int32_t pos; if (posTag->IsInt()) { @@ -286,7 +290,7 @@ JSTaggedValue BuiltinsString::CharCodeAt(EcmaRuntimeCallInfo *argv) if (pos < 0 || pos >= thisLen) { return GetTaggedDouble(base::NAN_VALUE); } - uint16_t ret = EcmaStringAccessor(thisHandle).Get(pos); + uint16_t ret = EcmaStringAccessor(thisFlat).Get(pos); return GetTaggedInt(ret); } @@ -300,20 +304,22 @@ JSTaggedValue BuiltinsString::CodePointAt(EcmaRuntimeCallInfo *argv) JSHandle thisTag(JSTaggedValue::RequireObjectCoercible(thread, GetThis(argv))); JSHandle thisHandle = JSTaggedValue::ToString(thread, thisTag); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + JSHandle thisFlat = JSHandle(thread, + EcmaStringAccessor::Flatten(thread->GetEcmaVM(), thisHandle)); JSHandle posTag = BuiltinsString::GetCallArg(argv, 0); JSTaggedNumber posVal = JSTaggedValue::ToNumber(thread, posTag); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); int32_t pos = base::NumberHelper::DoubleInRangeInt32(posVal.GetNumber()); - int32_t thisLen = static_cast(EcmaStringAccessor(thisHandle).GetLength()); + int32_t thisLen = static_cast(EcmaStringAccessor(thisFlat).GetLength()); if (pos < 0 || pos >= thisLen) { return JSTaggedValue::Undefined(); } - uint16_t first = EcmaStringAccessor(thisHandle).Get(pos); + uint16_t first = EcmaStringAccessor(thisFlat).Get(pos); if (first < base::utf_helper::DECODE_LEAD_LOW || first > base::utf_helper::DECODE_LEAD_HIGH || pos + 1 == thisLen) { return GetTaggedInt(first); } - uint16_t second = EcmaStringAccessor(thisHandle).Get(pos + 1); + uint16_t second = EcmaStringAccessor(thisFlat).Get(pos + 1); if (second < base::utf_helper::DECODE_TRAIL_LOW || second > base::utf_helper::DECODE_TRAIL_HIGH) { return GetTaggedInt(first); } @@ -395,7 +401,7 @@ JSTaggedValue BuiltinsString::EndsWith(EcmaRuntimeCallInfo *argv) return BuiltinsString::GetTaggedBoolean(false); } - int32_t idx = EcmaStringAccessor::IndexOf(*thisHandle, *searchHandle, start); + int32_t idx = EcmaStringAccessor::IndexOf(thread->GetEcmaVM(), thisHandle, searchHandle, start); if (idx == start) { return BuiltinsString::GetTaggedBoolean(true); } @@ -430,7 +436,7 @@ JSTaggedValue BuiltinsString::Includes(EcmaRuntimeCallInfo *argv) pos = base::NumberHelper::DoubleInRangeInt32(posVal.GetNumber()); } int32_t start = std::min(std::max(pos, 0), static_cast(thisLen)); - int32_t idx = EcmaStringAccessor::IndexOf(*thisHandle, *searchHandle, start); + int32_t idx = EcmaStringAccessor::IndexOf(thread->GetEcmaVM(), thisHandle, searchHandle, start); if (idx < 0 || idx > static_cast(thisLen)) { return BuiltinsString::GetTaggedBoolean(false); } @@ -463,7 +469,7 @@ JSTaggedValue BuiltinsString::IndexOf(EcmaRuntimeCallInfo *argv) pos = posVal.ToInt32(); } pos = std::min(std::max(pos, 0), static_cast(thisLen)); - int32_t res = EcmaStringAccessor::IndexOf(*thisHandle, *searchHandle, pos); + int32_t res = EcmaStringAccessor::IndexOf(thread->GetEcmaVM(), thisHandle, searchHandle, pos); if (res >= 0 && res < static_cast(thisLen)) { return GetTaggedInt(res); } @@ -498,7 +504,7 @@ JSTaggedValue BuiltinsString::LastIndexOf(EcmaRuntimeCallInfo *argv) } } pos = std::min(std::max(pos, 0), thisLen); - int32_t res = EcmaStringAccessor::LastIndexOf(*thisHandle, *searchHandle, pos); + int32_t res = EcmaStringAccessor::LastIndexOf(thread->GetEcmaVM(), thisHandle, searchHandle, pos); if (res >= 0 && res < thisLen) { return GetTaggedInt(res); } @@ -541,7 +547,7 @@ JSTaggedValue BuiltinsString::LocaleCompare(EcmaRuntimeCallInfo *argv) JSTaggedValue result = JSCollator::CompareStrings(icuCollator, thisHandle, thatHandle); return result; } - int32_t res = EcmaStringAccessor::Compare(*thisHandle, *thatHandle); + int32_t res = EcmaStringAccessor::Compare(thread->GetEcmaVM(), thisHandle, thatHandle); return GetTaggedInt(res); } @@ -626,8 +632,8 @@ JSTaggedValue BuiltinsString::MatchAll(EcmaRuntimeCallInfo *argv) // iii. If ? ToString(flags) does not contain "g", throw a TypeError exception. JSHandle flagString = JSTaggedValue::ToString(thread, flags); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - int32_t pos = EcmaStringAccessor::IndexOf( - *flagString, static_cast(gvalue->GetTaggedObject())); + int32_t pos = EcmaStringAccessor::IndexOf(ecmaVm, + flagString, JSHandle(gvalue)); if (pos == -1) { THROW_TYPE_ERROR_AND_RETURN(thread, "matchAll called with a non-global RegExp argument", @@ -670,7 +676,8 @@ JSTaggedValue BuiltinsString::Normalize(EcmaRuntimeCallInfo *argv) BUILTINS_API_TRACE(argv->GetThread(), String, Normalize); JSThread *thread = argv->GetThread(); [[maybe_unused]] EcmaHandleScope handleScope(thread); - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + auto vm = thread->GetEcmaVM(); + ObjectFactory *factory = vm->GetFactory(); JSHandle thisTag(JSTaggedValue::RequireObjectCoercible(thread, GetThis(argv))); JSHandle thisHandle = JSTaggedValue::ToString(thread, thisTag); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception()); @@ -691,13 +698,13 @@ JSTaggedValue BuiltinsString::Normalize(EcmaRuntimeCallInfo *argv) JSHandle nfkc = factory->NewFromASCII("NFKC"); JSHandle nfkd = factory->NewFromASCII("NFKD"); UNormalizationMode uForm; - if (EcmaStringAccessor::StringsAreEqual(*formValue, *nfc)) { + if (EcmaStringAccessor::StringsAreEqual(vm, formValue, nfc)) { uForm = UNORM_NFC; - } else if (EcmaStringAccessor::StringsAreEqual(*formValue, *nfd)) { + } else if (EcmaStringAccessor::StringsAreEqual(vm, formValue, nfd)) { uForm = UNORM_NFD; - } else if (EcmaStringAccessor::StringsAreEqual(*formValue, *nfkc)) { + } else if (EcmaStringAccessor::StringsAreEqual(vm, formValue, nfkc)) { uForm = UNORM_NFKC; - } else if (EcmaStringAccessor::StringsAreEqual(*formValue, *nfkd)) { + } else if (EcmaStringAccessor::StringsAreEqual(vm, formValue, nfkd)) { uForm = UNORM_NFKD; } else { THROW_RANGE_ERROR_AND_RETURN(thread, "compare not equal", JSTaggedValue::Exception()); @@ -765,7 +772,7 @@ JSTaggedValue BuiltinsString::Repeat(EcmaRuntimeCallInfo *argv) } bool isUtf8 = EcmaStringAccessor(thisHandle).IsUtf8(); - EcmaString *result = EcmaStringAccessor::AllocStringObject(thread->GetEcmaVM(), thisLen * count, isUtf8); + EcmaString *result = EcmaStringAccessor::CreateLineString(thread->GetEcmaVM(), thisLen * count, isUtf8); for (uint32_t index = 0; index < static_cast(count); ++index) { EcmaStringAccessor::ReadData(result, *thisHandle, index * thisLen, (count - index) * thisLen, thisLen); } @@ -842,7 +849,7 @@ JSTaggedValue BuiltinsString::Replace(EcmaRuntimeCallInfo *argv) // Search string for the first occurrence of searchString and let pos be the index within string of the first code // unit of the matched substring and let matched be searchString. If no occurrences of searchString were found, // return string. - int32_t pos = EcmaStringAccessor::IndexOf(*thisString, *searchString); + int32_t pos = EcmaStringAccessor::IndexOf(ecmaVm, thisString, searchString); if (pos == -1) { return thisString.GetTaggedValue(); } @@ -917,7 +924,7 @@ JSTaggedValue BuiltinsString::ReplaceAll(EcmaRuntimeCallInfo *argv) JSHandle flagString = JSTaggedValue::ToString(thread, flags); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); JSHandle gString(globalConst->GetHandledGString()); - int32_t pos = EcmaStringAccessor::IndexOf(*flagString, *gString); + int32_t pos = EcmaStringAccessor::IndexOf(ecmaVm, flagString, gString); if (pos == -1) { THROW_TYPE_ERROR_AND_RETURN(thread, "string.prototype.replaceAll called with a non-global RegExp argument", @@ -964,7 +971,7 @@ JSTaggedValue BuiltinsString::ReplaceAll(EcmaRuntimeCallInfo *argv) std::u16string stringRealReplaceStr; std::u16string stringSuffixString; // 10. Let position be ! StringIndexOf(string, searchString, 0). - int32_t pos = EcmaStringAccessor::IndexOf(*thisString, *searchString); + int32_t pos = EcmaStringAccessor::IndexOf(ecmaVm, thisString, searchString); int32_t endOfLastMatch = 0; bool canBeCompress = true; JSHandle undefined = globalConst->GetHandledUndefined(); @@ -1008,7 +1015,7 @@ JSTaggedValue BuiltinsString::ReplaceAll(EcmaRuntimeCallInfo *argv) } stringBuilder = stringBuilder + stringPrefixString + stringRealReplaceStr; endOfLastMatch = pos + searchLength; - pos = EcmaStringAccessor::IndexOf(*thisString, *searchString, pos + advanceBy); + pos = EcmaStringAccessor::IndexOf(ecmaVm, thisString, searchString, pos + advanceBy); } if (endOfLastMatch < static_cast(EcmaStringAccessor(thisString).GetLength())) { @@ -1039,18 +1046,20 @@ JSTaggedValue BuiltinsString::GetSubstitution(JSThread *thread, const JSHandleGetEcmaVM(); ObjectFactory *factory = ecmaVm->GetFactory(); JSHandle dollarString = JSHandle::Cast(thread->GlobalConstants()->GetHandledDollarString()); - int32_t replaceLength = static_cast(EcmaStringAccessor(replacement).GetLength()); + JSHandle replacementFlat = JSHandle( + thread, EcmaStringAccessor::Flatten(ecmaVm, replacement)); + int32_t replaceLength = static_cast(EcmaStringAccessor(replacementFlat).GetLength()); int32_t tailPos = position + static_cast(EcmaStringAccessor(matched).GetLength()); - int32_t nextDollarIndex = EcmaStringAccessor::IndexOf(*replacement, *dollarString); + int32_t nextDollarIndex = EcmaStringAccessor::IndexOf(ecmaVm, replacementFlat, dollarString); if (nextDollarIndex < 0) { - return replacement.GetTaggedValue(); + return replacementFlat.GetTaggedValue(); } std::u16string stringBuilder; bool canBeCompress = true; if (nextDollarIndex > 0) { - stringBuilder = EcmaStringAccessor(replacement).ToU16String(nextDollarIndex); - if (EcmaStringAccessor(replacement).IsUtf16()) { + stringBuilder = EcmaStringAccessor(replacementFlat).ToU16String(nextDollarIndex); + if (EcmaStringAccessor(replacementFlat).IsUtf16()) { canBeCompress = false; } } @@ -1066,7 +1075,7 @@ JSTaggedValue BuiltinsString::GetSubstitution(JSThread *thread, const JSHandleNewFromUtf16LiteralNotCompress(uint16tData, stringBuilder.length()).GetTaggedValue(); } int continueFromIndex = -1; - uint16_t peek = EcmaStringAccessor(replacement).Get(peekIndex); + uint16_t peek = EcmaStringAccessor(replacementFlat).Get(peekIndex); switch (peek) { case '$': // $$ stringBuilder += '$'; @@ -1118,7 +1127,7 @@ JSTaggedValue BuiltinsString::GetSubstitution(JSThread *thread, const JSHandle= '0' && nextPeek <= '9') { constexpr uint32_t TEN_BASE = 10; uint32_t newScaledIndex = scaledIndex * TEN_BASE + (nextPeek - '0'); @@ -1153,14 +1162,14 @@ JSTaggedValue BuiltinsString::GetSubstitution(JSThread *thread, const JSHandle greaterSymString = factory->NewFromASCII(">"); - int32_t pos = EcmaStringAccessor::IndexOf(*replacement, *greaterSymString, peekIndex); + int32_t pos = EcmaStringAccessor::IndexOf(ecmaVm, replacementFlat, greaterSymString, peekIndex); if (pos == -1) { stringBuilder += '$'; continueFromIndex = peekIndex; break; } JSHandle groupName(thread, - EcmaStringAccessor::FastSubString(ecmaVm, replacement, + EcmaStringAccessor::FastSubString(ecmaVm, replacementFlat, peekIndex + 1, pos - peekIndex - 1)); JSHandle names(groupName); JSHandle capture = JSObject::GetProperty(thread, namedCaptures, names).GetValue(); @@ -1182,10 +1191,10 @@ JSTaggedValue BuiltinsString::GetSubstitution(JSThread *thread, const JSHandle continueFromIndex) { EcmaString *nextAppend = EcmaStringAccessor::FastSubString( - ecmaVm, replacement, continueFromIndex, nextDollarIndex - continueFromIndex); + ecmaVm, replacementFlat, continueFromIndex, nextDollarIndex - continueFromIndex); stringBuilder += EcmaStringAccessor(nextAppend).ToU16String(); if (EcmaStringAccessor(nextAppend).IsUtf16()) { canBeCompress = false; @@ -1353,7 +1362,7 @@ JSTaggedValue BuiltinsString::Split(EcmaRuntimeCallInfo *argv) } // If S.length = 0, then if (thisLength == 0) { - if (EcmaStringAccessor::IndexOf(*thisString, *seperatorString) != -1) { + if (EcmaStringAccessor::IndexOf(ecmaVm, thisString, seperatorString) != -1) { return resultArray.GetTaggedValue(); } JSObject::CreateDataProperty(thread, resultArray, 0, JSHandle(thisString)); @@ -1376,7 +1385,7 @@ JSTaggedValue BuiltinsString::Split(EcmaRuntimeCallInfo *argv) return resultArray.GetTaggedValue(); } int32_t index = 0; - int32_t pos = EcmaStringAccessor::IndexOf(*thisString, *seperatorString); + int32_t pos = EcmaStringAccessor::IndexOf(ecmaVm, thisString, seperatorString); while (pos != -1) { EcmaString *elementString = EcmaStringAccessor::FastSubString(ecmaVm, thisString, index, pos - index); JSHandle elementTag(thread, elementString); @@ -1387,7 +1396,7 @@ JSTaggedValue BuiltinsString::Split(EcmaRuntimeCallInfo *argv) return resultArray.GetTaggedValue(); } index = pos + seperatorLength; - pos = EcmaStringAccessor::IndexOf(*thisString, *seperatorString, index); + pos = EcmaStringAccessor::IndexOf(ecmaVm, thisString, seperatorString, index); } EcmaString *elementString = EcmaStringAccessor::FastSubString(ecmaVm, thisString, index, thisLength - index); JSHandle elementTag(thread, elementString); @@ -1432,7 +1441,7 @@ JSTaggedValue BuiltinsString::StartsWith(EcmaRuntimeCallInfo *argv) if (static_cast(pos) + searchLen > thisLen) { return BuiltinsString::GetTaggedBoolean(false); } - int32_t res = EcmaStringAccessor::IndexOf(*thisHandle, *searchHandle, pos); + int32_t res = EcmaStringAccessor::IndexOf(thread->GetEcmaVM(), thisHandle, searchHandle, pos); if (res == pos) { return BuiltinsString::GetTaggedBoolean(true); } diff --git a/ecmascript/builtins/builtins_typedarray.cpp b/ecmascript/builtins/builtins_typedarray.cpp index 4161d2fbdb..8254025139 100644 --- a/ecmascript/builtins/builtins_typedarray.cpp +++ b/ecmascript/builtins/builtins_typedarray.cpp @@ -788,7 +788,7 @@ JSTaggedValue BuiltinsTypedArray::Join(EcmaRuntimeCallInfo *argv) } } allocateLength += sepLength * (length - 1); - auto newString = EcmaStringAccessor::AllocStringObject(thread->GetEcmaVM(), allocateLength, isOneByte); + auto newString = EcmaStringAccessor::CreateLineString(thread->GetEcmaVM(), allocateLength, isOneByte); int current = 0; DISALLOW_GARBAGE_COLLECTION; for (uint32_t k = 0; k < length; k++) { diff --git a/ecmascript/builtins/tests/builtins_array_test.cpp b/ecmascript/builtins/tests/builtins_array_test.cpp index 93a4171f3e..5dcc313ee4 100644 --- a/ecmascript/builtins/tests/builtins_array_test.cpp +++ b/ecmascript/builtins/tests/builtins_array_test.cpp @@ -1426,9 +1426,8 @@ HWTEST_F_L0(BuiltinsArrayTest, Join) JSTaggedValue result = Array::Join(ecmaRuntimeCallInfo1); TestHelper::TearDownFrame(thread, prev); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); - [[maybe_unused]] auto *res = EcmaString::Cast(resultHandle.GetTaggedValue().GetTaggedObject()); - ASSERT_EQ(EcmaStringAccessor::Compare(res, *str), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, str), 0); } HWTEST_F_L0(BuiltinsArrayTest, ToString) @@ -1458,9 +1457,8 @@ HWTEST_F_L0(BuiltinsArrayTest, ToString) JSTaggedValue result = Array::ToString(ecmaRuntimeCallInfo1); TestHelper::TearDownFrame(thread, prev); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); - [[maybe_unused]] auto *res = EcmaString::Cast(resultHandle.GetTaggedValue().GetTaggedObject()); - ASSERT_EQ(EcmaStringAccessor::Compare(res, *str), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, str), 0); } HWTEST_F_L0(BuiltinsArrayTest, Includes) diff --git a/ecmascript/builtins/tests/builtins_bigint_test.cpp b/ecmascript/builtins/tests/builtins_bigint_test.cpp index 00557db2b9..72891df710 100644 --- a/ecmascript/builtins/tests/builtins_bigint_test.cpp +++ b/ecmascript/builtins/tests/builtins_bigint_test.cpp @@ -117,7 +117,7 @@ HWTEST_F_L0(BuiltinsBigIntTest, AsIntN_001) JSHandle bigIntHandle(thread, result); JSHandle resultStr = BigInt::ToString(thread, bigIntHandle); JSHandle str = factory->NewFromASCII("9223372036854775807"); - EXPECT_EQ(EcmaStringAccessor::Compare(*resultStr, *str), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultStr, str), 0); } // AsIntN(64, (2 ^ 63)) @@ -141,7 +141,7 @@ HWTEST_F_L0(BuiltinsBigIntTest, AsIntN_002) JSHandle bigIntHandle(thread, result); JSHandle resultStr = BigInt::ToString(thread, bigIntHandle); JSHandle str = factory->NewFromASCII("-9223372036854775808"); - EXPECT_EQ(EcmaStringAccessor::Compare(*resultStr, *str), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultStr, str), 0); } // AsUintN(64, (2 ^ 64 - 1)) @@ -165,7 +165,7 @@ HWTEST_F_L0(BuiltinsBigIntTest, AsUintN_001) JSHandle bigIntHandle(thread, result); JSHandle resultStr = BigInt::ToString(thread, bigIntHandle); JSHandle str = factory->NewFromASCII("18446744073709551615"); - EXPECT_EQ(EcmaStringAccessor::Compare(*resultStr, *str), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultStr, str), 0); } // AsUintN(64, (2 ^ 64)) @@ -189,7 +189,7 @@ HWTEST_F_L0(BuiltinsBigIntTest, AsUintN_002) JSHandle bigIntHandle(thread, result); JSHandle resultStr = BigInt::ToString(thread, bigIntHandle); JSHandle str = factory->NewFromASCII("0"); - EXPECT_EQ(EcmaStringAccessor::Compare(*resultStr, *str), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultStr, str), 0); } // using locale @@ -223,7 +223,7 @@ HWTEST_F_L0(BuiltinsBigIntTest, ToLocaleString_001) EXPECT_TRUE(result2.IsString()); JSHandle ecmaStrHandle(thread, result2); JSHandle resultStr(factory->NewFromASCII("123.456.789.123.456.789")); - EXPECT_EQ(EcmaStringAccessor::Compare(*ecmaStrHandle, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, ecmaStrHandle, resultStr), 0); } // using locale and options @@ -546,14 +546,14 @@ HWTEST_F_L0(BuiltinsBigIntTest, StringToBigInt) ASSERT_TRUE(bigint->IsBigInt()); str = BigInt::ToString(thread, JSHandle::Cast(bigint), BigInt::HEXADECIMAL); parma = JSHandle(factory->NewFromASCII("ffff")); - ASSERT_EQ(EcmaStringAccessor::Compare(*str, reinterpret_cast(parma->GetRawData())), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, str, JSHandle(parma)), 0); parma = JSHandle(factory->NewFromASCII("0XFFFF")); bigint = JSHandle(thread, base::NumberHelper::StringToBigInt(thread, parma)); ASSERT_TRUE(bigint->IsBigInt()); str = BigInt::ToString(thread, JSHandle::Cast(bigint), BigInt::HEXADECIMAL); parma = JSHandle(factory->NewFromASCII("ffff")); - ASSERT_EQ(EcmaStringAccessor::Compare(*str, reinterpret_cast(parma->GetRawData())), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, str, JSHandle(parma)), 0); // binary string parma = JSHandle(factory->NewFromASCII("0b11111111")); @@ -561,14 +561,14 @@ HWTEST_F_L0(BuiltinsBigIntTest, StringToBigInt) ASSERT_TRUE(bigint->IsBigInt()); str = BigInt::ToString(thread, JSHandle::Cast(bigint), BigInt::BINARY); parma = JSHandle(factory->NewFromASCII("11111111")); - ASSERT_EQ(EcmaStringAccessor::Compare(*str, reinterpret_cast(parma->GetRawData())), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, str, JSHandle(parma)), 0); parma = JSHandle(factory->NewFromASCII("0B11111111")); bigint = JSHandle(thread, base::NumberHelper::StringToBigInt(thread, parma)); ASSERT_TRUE(bigint->IsBigInt()); str = BigInt::ToString(thread, JSHandle::Cast(bigint), BigInt::BINARY); parma = JSHandle(factory->NewFromASCII("11111111")); - ASSERT_EQ(EcmaStringAccessor::Compare(*str, reinterpret_cast(parma->GetRawData())), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, str, JSHandle(parma)), 0); // octal string parma = JSHandle(factory->NewFromASCII("0o123456")); @@ -576,21 +576,21 @@ HWTEST_F_L0(BuiltinsBigIntTest, StringToBigInt) ASSERT_TRUE(bigint->IsBigInt()); str = BigInt::ToString(thread, JSHandle::Cast(bigint), BigInt::OCTAL); parma = JSHandle(factory->NewFromASCII("123456")); - ASSERT_EQ(EcmaStringAccessor::Compare(*str, reinterpret_cast(parma->GetRawData())), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, str, JSHandle(parma)), 0); parma = JSHandle(factory->NewFromASCII("0O123456")); bigint = JSHandle(thread, base::NumberHelper::StringToBigInt(thread, parma)); ASSERT_TRUE(bigint->IsBigInt()); str = BigInt::ToString(thread, JSHandle::Cast(bigint), BigInt::OCTAL); parma = JSHandle(factory->NewFromASCII("123456")); - ASSERT_EQ(EcmaStringAccessor::Compare(*str, reinterpret_cast(parma->GetRawData())), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, str, JSHandle(parma)), 0); // decimal string parma = JSHandle(factory->NewFromASCII("999999999")); bigint = JSHandle(thread, base::NumberHelper::StringToBigInt(thread, parma)); ASSERT_TRUE(bigint->IsBigInt()); str = BigInt::ToString(thread, JSHandle::Cast(bigint)); - ASSERT_EQ(EcmaStringAccessor::Compare(*str, reinterpret_cast(parma->GetRawData())), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, str, JSHandle(parma)), 0); // string has space parma = JSHandle(factory->NewFromASCII(" 123 ")); diff --git a/ecmascript/builtins/tests/builtins_boolean_test.cpp b/ecmascript/builtins/tests/builtins_boolean_test.cpp index fec9562793..9e448af6fb 100644 --- a/ecmascript/builtins/tests/builtins_boolean_test.cpp +++ b/ecmascript/builtins/tests/builtins_boolean_test.cpp @@ -130,7 +130,7 @@ HWTEST_F_L0(BuiltinsBooleanTest, BooleanPrototypeToString) ASSERT_TRUE(result.IsString()); JSHandle res(thread, reinterpret_cast(result.GetRawData())); auto ruler = thread->GetEcmaVM()->GetFactory()->NewFromASCII("false"); - ASSERT_EQ(EcmaStringAccessor::Compare(*res, *ruler), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, res, ruler), 0); } // (new Boolean(true)).toString() @@ -152,7 +152,7 @@ HWTEST_F_L0(BuiltinsBooleanTest, BooleanPrototypeToString1) ASSERT_TRUE(result.IsString()); JSHandle res(thread, reinterpret_cast(result.GetRawData())); auto ruler = thread->GetEcmaVM()->GetFactory()->NewFromASCII("true"); - ASSERT_EQ(EcmaStringAccessor::Compare(*res, *ruler), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, res, ruler), 0); } // true.valueOf() diff --git a/ecmascript/builtins/tests/builtins_collator_test.cpp b/ecmascript/builtins/tests/builtins_collator_test.cpp index 660e985f16..39578685e0 100644 --- a/ecmascript/builtins/tests/builtins_collator_test.cpp +++ b/ecmascript/builtins/tests/builtins_collator_test.cpp @@ -256,7 +256,7 @@ HWTEST_F_L0(BuiltinsCollatorTest, Compare_002) JSTaggedValue result = BuiltinsArray::Join(ecmaRuntimeCallInfo3); TestHelper::TearDownFrame(thread, prev); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); - EXPECT_EQ(EcmaStringAccessor::Compare(*resultHandle, *str), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, str), 0); } // compare with options("search") diff --git a/ecmascript/builtins/tests/builtins_date_time_format_test.cpp b/ecmascript/builtins/tests/builtins_date_time_format_test.cpp index 01a5d13b88..22b9ebc3b7 100644 --- a/ecmascript/builtins/tests/builtins_date_time_format_test.cpp +++ b/ecmascript/builtins/tests/builtins_date_time_format_test.cpp @@ -279,7 +279,7 @@ HWTEST_F_L0(BuiltinsDateTimeFormatTest, FormatRange_001) JSHandle handleStr(thread, result); JSHandle resultStr = factory->NewFromUtf8("2020/11/1周日 24:00:00 – 2021/7/1周四 24:00:00"); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleStr, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleStr, resultStr), 0); } // FormatRange(en) @@ -304,7 +304,7 @@ HWTEST_F_L0(BuiltinsDateTimeFormatTest, FormatRange_002) JSHandle handleStr(thread, result); JSHandle resultStr = factory->NewFromUtf8("Fri, 1/1/2021, 24:00:00 – Mon, 3/1/2021, 24:00:00"); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleStr, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleStr, resultStr), 0); } HWTEST_F_L0(BuiltinsDateTimeFormatTest, FormatRangeToParts) diff --git a/ecmascript/builtins/tests/builtins_errors_test.cpp b/ecmascript/builtins/tests/builtins_errors_test.cpp index 927cbe3f26..307341fd76 100644 --- a/ecmascript/builtins/tests/builtins_errors_test.cpp +++ b/ecmascript/builtins/tests/builtins_errors_test.cpp @@ -90,16 +90,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, GetJSErrorObject) */ JSHandle msgValue( JSObject::GetProperty(thread, JSHandle(handleObj), msgKey).GetValue()); - EXPECT_EQ(EcmaStringAccessor::Compare(reinterpret_cast(msgValue->GetRawData()), - reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("")).GetRawData())), - 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, + JSHandle(msgValue), factory->NewFromASCII("")), 0); JSHandle nameValue( JSObject::GetProperty(thread, JSHandle(handleObj), nameKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("TypeError")).GetRawData()), - reinterpret_cast(nameValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("TypeError"), JSHandle(nameValue)), 0); } /* @@ -116,16 +112,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, GetJSErrorWithMessage) JSHandle nameKey = thread->GlobalConstants()->GetHandledNameString(); JSHandle msgValue( JSObject::GetProperty(thread, JSHandle(handleObj), msgKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("I am type error")).GetRawData()), - reinterpret_cast(msgValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("I am type error"), JSHandle(msgValue)), 0); JSHandle nameValue( JSObject::GetProperty(thread, JSHandle(handleObj), nameKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("TypeError")).GetRawData()), - reinterpret_cast(nameValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("TypeError"), JSHandle(nameValue)), 0); } /* @@ -154,16 +146,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, ErrorNoParameterConstructor) JSHandle nameKey = thread->GlobalConstants()->GetHandledNameString(); JSHandle msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare( - reinterpret_cast(ecmascript::JSTaggedValue(*factory->NewFromASCII("")).GetRawData()), - reinterpret_cast(msgValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII(""), JSHandle(msgValue)), 0); JSHandle nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare( - reinterpret_cast(ecmascript::JSTaggedValue(*factory->NewFromASCII("Error")).GetRawData()), - reinterpret_cast(nameValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("Error"), JSHandle(nameValue)), 0); } /* @@ -194,16 +182,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, ErrorParameterConstructor) JSHandle nameKey = thread->GlobalConstants()->GetHandledNameString(); JSHandle msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("Hello Error!")).GetRawData()), - reinterpret_cast(msgValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("Hello Error!"), JSHandle(msgValue)), 0); JSHandle nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("Error")).GetRawData()), - reinterpret_cast(nameValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("Error"), JSHandle(nameValue)), 0); } /* @@ -228,10 +212,7 @@ HWTEST_F_L0(BuiltinsErrorsTest, ErrorNoParameterToString) JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); EXPECT_TRUE(result.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("Error")).GetRawData()), - reinterpret_cast(*resultHandle)), - 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, factory->NewFromASCII("Error"), resultHandle), 0); } /* @@ -261,10 +242,7 @@ HWTEST_F_L0(BuiltinsErrorsTest, ErrorToString) JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); EXPECT_TRUE(result.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("Error: This is Error!")).GetRawData()), - *resultHandle), - 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, factory->NewFromASCII("Error: This is Error!"), resultHandle), 0); } /* @@ -293,15 +271,11 @@ HWTEST_F_L0(BuiltinsErrorsTest, RangeErrorNoParameterConstructor) JSHandle nameKey = thread->GlobalConstants()->GetHandledNameString(); JSHandle msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare( - reinterpret_cast(ecmascript::JSTaggedValue(*factory->NewFromASCII("")).GetRawData()), - reinterpret_cast(JSTaggedValue(msgValue.GetTaggedValue()).GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII(""), JSHandle(msgValue)), 0); JSHandle nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("RangeError")).GetRawData()), - reinterpret_cast(JSTaggedValue(nameValue.GetTaggedValue()).GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("RangeError"), JSHandle(nameValue)), 0); } /* @@ -332,16 +306,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, RangeErrorParameterConstructor) JSHandle nameKey = thread->GlobalConstants()->GetHandledNameString(); JSHandle msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("Hello RangeError!")).GetRawData()), - reinterpret_cast(msgValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("Hello RangeError!"), JSHandle(msgValue)), 0); JSHandle nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("RangeError")).GetRawData()), - reinterpret_cast(nameValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("RangeError"), JSHandle(nameValue)), 0); } /* @@ -367,10 +337,8 @@ HWTEST_F_L0(BuiltinsErrorsTest, RangeErrorNoParameterToString) EXPECT_TRUE(result.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("RangeError")).GetRawData()), - reinterpret_cast(resultHandle->GetRawData())), - 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("RangeError"), JSHandle(resultHandle)), 0); } /* @@ -399,7 +367,8 @@ HWTEST_F_L0(BuiltinsErrorsTest, RangeErrorToString) JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); EXPECT_TRUE(result.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(*factory->NewFromASCII("RangeError: This is RangeError!"), *resultHandle), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("RangeError: This is RangeError!"), resultHandle), 0); } // new ReferenceError() @@ -428,16 +397,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, ReferenceErrorNoParameterConstructor) JSHandle nameKey = thread->GlobalConstants()->GetHandledNameString(); JSHandle msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("")).GetRawData()), - reinterpret_cast(msgValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII(""), JSHandle(msgValue)), 0); JSHandle nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("ReferenceError")).GetRawData()), - reinterpret_cast(nameValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("ReferenceError"), JSHandle(nameValue)), 0); } /* @@ -466,16 +431,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, ReferenceErrorParameterConstructor) JSHandle msgKey(factory->NewFromASCII("message")); JSHandle nameKey = thread->GlobalConstants()->GetHandledNameString(); JSHandle msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("Hello ReferenceError!")).GetRawData()), - reinterpret_cast(msgValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("Hello ReferenceError!"), JSHandle(msgValue)), 0); JSHandle nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("ReferenceError")).GetRawData()), - reinterpret_cast(nameValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("ReferenceError"), JSHandle(nameValue)), 0); } /* @@ -499,10 +460,7 @@ HWTEST_F_L0(BuiltinsErrorsTest, ReferenceErrorNoParameterToString) JSTaggedValue result = ReferenceError::ToString(ecmaRuntimeCallInfo); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); EXPECT_TRUE(result.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("ReferenceError")).GetRawData()), - *resultHandle), - 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, factory->NewFromASCII("ReferenceError"), resultHandle), 0); } /* @@ -530,10 +488,8 @@ HWTEST_F_L0(BuiltinsErrorsTest, ReferenceErrorToString) JSTaggedValue result = ReferenceError::ToString(ecmaRuntimeCallInfo); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); EXPECT_TRUE(result.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare( - *factory->NewFromASCII("ReferenceError: This is ReferenceError!"), - *resultHandle), - 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("ReferenceError: This is ReferenceError!"), resultHandle), 0); } /* @@ -561,16 +517,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, TypeErrorNoParameterConstructor) JSHandle nameKey = thread->GlobalConstants()->GetHandledNameString(); JSHandle msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare( - reinterpret_cast(ecmascript::JSTaggedValue(*factory->NewFromASCII("")).GetRawData()), - reinterpret_cast(msgValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII(""), JSHandle(msgValue)), 0); JSHandle nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue()); - EXPECT_EQ(EcmaStringAccessor::Compare( - reinterpret_cast(JSTaggedValue(nameValue.GetTaggedValue()).GetRawData()), - reinterpret_cast(JSTaggedValue(nameValue.GetTaggedValue()).GetRawData())), - 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, + JSHandle(nameValue), JSHandle(nameValue)), 0); } /* @@ -600,16 +552,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, TypeErrorParameterConstructor) JSHandle nameKey = thread->GlobalConstants()->GetHandledNameString(); JSHandle msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("Hello TypeError!")).GetRawData()), - reinterpret_cast(msgValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("Hello TypeError!"), JSHandle(msgValue)), 0); JSHandle nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("TypeError")).GetRawData()), - reinterpret_cast(nameValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("TypeError"), JSHandle(nameValue)), 0); } /* @@ -633,10 +581,7 @@ HWTEST_F_L0(BuiltinsErrorsTest, TypeErrorNoParameterToString) JSTaggedValue result = TypeError::ToString(ecmaRuntimeCallInfo); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); EXPECT_TRUE(result.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("TypeError")).GetRawData()), - *resultHandle), - 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, factory->NewFromASCII("TypeError"), resultHandle), 0); } /* @@ -664,8 +609,8 @@ HWTEST_F_L0(BuiltinsErrorsTest, TypeErrorToString) JSTaggedValue result = TypeError::ToString(ecmaRuntimeCallInfo); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); EXPECT_TRUE(result.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare( - *factory->NewFromASCII("TypeError: This is TypeError!"), *resultHandle), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("TypeError: This is TypeError!"), resultHandle), 0); } /* @@ -693,16 +638,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, URIErrorNoParameterConstructor) JSHandle nameKey = thread->GlobalConstants()->GetHandledNameString(); JSHandle msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("")).GetRawData()), - reinterpret_cast(msgValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII(""), JSHandle(msgValue)), 0); JSHandle nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("URIError")).GetRawData()), - reinterpret_cast(nameValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("URIError"), JSHandle(nameValue)), 0); } /* @@ -732,16 +673,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, URIErrorParameterConstructor) JSHandle nameKey = thread->GlobalConstants()->GetHandledNameString(); JSHandle msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("Hello URIError!")).GetRawData()), - reinterpret_cast(msgValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("Hello URIError!"), JSHandle(msgValue)), 0); JSHandle nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("URIError")).GetRawData()), - reinterpret_cast(nameValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("URIError"), JSHandle(nameValue)), 0); } /* @@ -766,10 +703,7 @@ HWTEST_F_L0(BuiltinsErrorsTest, URIErrorNoParameterToString) JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); EXPECT_TRUE(result.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("URIError")).GetRawData()), - *resultHandle), - 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, factory->NewFromASCII("URIError"), resultHandle), 0); } /* @@ -799,10 +733,8 @@ HWTEST_F_L0(BuiltinsErrorsTest, URIErrorToString) JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); EXPECT_TRUE(result.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("URIError: This is URIError!")).GetRawData()), - *resultHandle), - 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("URIError: This is URIError!"), resultHandle), 0); } /* @@ -830,16 +762,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, SyntaxErrorNoParameterConstructor) JSHandle nameKey = thread->GlobalConstants()->GetHandledNameString(); JSHandle msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("")).GetRawData()), - reinterpret_cast(msgValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII(""), JSHandle(msgValue)), 0); JSHandle nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("SyntaxError")).GetRawData()), - reinterpret_cast(nameValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("SyntaxError"), JSHandle(nameValue)), 0); } /* @@ -869,16 +797,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, SyntaxErrorParameterConstructor) JSHandle nameKey = thread->GlobalConstants()->GetHandledNameString(); JSHandle msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("Hello SyntaxError!")).GetRawData()), - reinterpret_cast(msgValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("Hello SyntaxError!"), JSHandle(msgValue)), 0); JSHandle nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("SyntaxError")).GetRawData()), - reinterpret_cast(nameValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("SyntaxError"), JSHandle(nameValue)), 0); } /* @@ -903,10 +827,7 @@ HWTEST_F_L0(BuiltinsErrorsTest, SyntaxErrorNoParameterToString) JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); EXPECT_TRUE(result.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("SyntaxError")).GetRawData()), - *resultHandle), - 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, factory->NewFromASCII("SyntaxError"), resultHandle), 0); } /* @@ -935,8 +856,8 @@ HWTEST_F_L0(BuiltinsErrorsTest, SyntaxErrorToString) JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); EXPECT_TRUE(result.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare( - *factory->NewFromASCII("SyntaxError: This is SyntaxError!"), *resultHandle), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("SyntaxError: This is SyntaxError!"), resultHandle), 0); } /* @@ -964,16 +885,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, EvalErrorNoParameterConstructor) JSHandle nameKey = thread->GlobalConstants()->GetHandledNameString(); JSHandle msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("")).GetRawData()), - reinterpret_cast(msgValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII(""), JSHandle(msgValue)), 0); JSHandle nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("EvalError")).GetRawData()), - reinterpret_cast(nameValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("EvalError"), JSHandle(nameValue)), 0); } /* @@ -1003,16 +920,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, EvalErrorParameterConstructor) JSHandle nameKey = thread->GlobalConstants()->GetHandledNameString(); JSHandle msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("Hello EvalError!")).GetRawData()), - reinterpret_cast(msgValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("Hello EvalError!"), JSHandle(msgValue)), 0); JSHandle nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue()); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("EvalError")).GetRawData()), - reinterpret_cast(nameValue->GetRawData())), - 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("EvalError"), JSHandle(nameValue)), 0); } /* @@ -1035,10 +948,7 @@ HWTEST_F_L0(BuiltinsErrorsTest, EvalErrorNoParameterToString) JSTaggedValue result = EvalError::ToString(ecmaRuntimeCallInfo); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); EXPECT_TRUE(result.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(reinterpret_cast( - ecmascript::JSTaggedValue(*factory->NewFromASCII("EvalError")).GetRawData()), - *resultHandle), - 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, factory->NewFromASCII("EvalError"), resultHandle), 0); } /* @@ -1067,7 +977,7 @@ HWTEST_F_L0(BuiltinsErrorsTest, EvalErrorToString) JSTaggedValue result = EvalError::ToString(ecmaRuntimeCallInfo); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); EXPECT_TRUE(result.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare( - *factory->NewFromASCII("EvalError: This is EvalError!"), *resultHandle), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("EvalError: This is EvalError!"), resultHandle), 0); } } // namespace panda::test diff --git a/ecmascript/builtins/tests/builtins_function_test.cpp b/ecmascript/builtins/tests/builtins_function_test.cpp index c6ea5da1ef..4cf9408b36 100644 --- a/ecmascript/builtins/tests/builtins_function_test.cpp +++ b/ecmascript/builtins/tests/builtins_function_test.cpp @@ -205,7 +205,7 @@ HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeBind) JSHandle resultFuncHandle(thread, *resultFunc); JSHandle resultName(JSObject::GetProperty(thread, resultFuncHandle, nameKey).GetValue()); JSHandle boundTarget = factory->NewFromASCII("bound target"); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultName, *boundTarget), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultName, boundTarget), 0); // test length property JSHandle lengthKey = globalConst->GetHandledLengthString(); JSHandle resultLength(JSObject::GetProperty(thread, resultFuncHandle, lengthKey).GetValue()); @@ -260,7 +260,7 @@ HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeBind1) JSHandle resultFuncHandle(thread, *resultFunc); JSHandle resultName(JSObject::GetProperty(thread, resultFuncHandle, nameKey).GetValue()); JSHandle rulerName = factory->NewFromASCII("bound target1"); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultName, *rulerName), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultName, rulerName), 0); // test length property JSHandle lengthKey = globalConst->GetHandledLengthString(); JSHandle resultLength(JSObject::GetProperty(thread, resultFuncHandle, lengthKey).GetValue()); @@ -316,7 +316,7 @@ HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeBind2) JSHandle resultFuncHandle(resultFunc); JSHandle resultName(JSObject::GetProperty(thread, resultFuncHandle, nameKey).GetValue()); JSHandle rulerName = factory->NewFromASCII("bound "); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultName, *rulerName), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultName, rulerName), 0); // test length property JSHandle lengthKey = globalConst->GetHandledLengthString(); JSHandle resultLength(JSObject::GetProperty(thread, resultFuncHandle, lengthKey).GetValue()); @@ -453,7 +453,7 @@ HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeToString) JSTaggedValue result = BuiltinsFunction::FunctionPrototypeToString(ecmaRuntimeCallInfo); ASSERT_TRUE(result.IsString()); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); - JSTaggedValue test = factory->NewFromASCII("function call() { [native code] }").GetTaggedValue(); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast(test.GetRawData())), 0); + JSHandle test = factory->NewFromASCII("function call() { [native code] }"); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0); } } // namespace panda::test diff --git a/ecmascript/builtins/tests/builtins_locale_test.cpp b/ecmascript/builtins/tests/builtins_locale_test.cpp index 502f381dbd..a32dd5aaf0 100644 --- a/ecmascript/builtins/tests/builtins_locale_test.cpp +++ b/ecmascript/builtins/tests/builtins_locale_test.cpp @@ -166,7 +166,7 @@ HWTEST_F_L0(BuiltinsLocaleTest, ToString) JSHandle handleEcmaStr(thread, result); JSHandle resultStr( factory->NewFromASCII("en-Latn-US-u-ca-chinese-co-compat-hc-h24-kn-nu-mong")); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr, *resultStr), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr, resultStr), 0); } HWTEST_F_L0(BuiltinsLocaleTest, GetBaseName) diff --git a/ecmascript/builtins/tests/builtins_number_test.cpp b/ecmascript/builtins/tests/builtins_number_test.cpp index 0b7cb0d13f..79e8bd50f1 100644 --- a/ecmascript/builtins/tests/builtins_number_test.cpp +++ b/ecmascript/builtins/tests/builtins_number_test.cpp @@ -418,7 +418,7 @@ HWTEST_F_L0(BuiltinsNumberTest, StringToDoubleFlags) { JSHandle str; Span sp; - [[maybe_unused]] CVector buf; + CVector buf; // flags of IGNORE_TRAILING @@ -500,7 +500,7 @@ HWTEST_F_L0(BuiltinsNumberTest, StringToDoubleRadix) { JSHandle str; Span sp; - [[maybe_unused]] CVector buf; + CVector buf; int radix; radix = 0; // default 10 @@ -586,42 +586,43 @@ HWTEST_F_L0(BuiltinsNumberTest, NumberToString) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle res = factory->NewFromASCII("100"); - ASSERT_EQ(EcmaStringAccessor::Compare(*base::NumberHelper::NumberToString(thread, JSTaggedValue(100)), *res), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + base::NumberHelper::NumberToString(thread, JSTaggedValue(100)), res), 0); res = factory->NewFromASCII("11223344"); - ASSERT_EQ(EcmaStringAccessor::Compare( - *base::NumberHelper::NumberToString(thread, JSTaggedValue(11223344)), *res), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + base::NumberHelper::NumberToString(thread, JSTaggedValue(11223344)), res), 0); res = factory->NewFromASCII("1234567890"); - ASSERT_EQ(EcmaStringAccessor::Compare( - *base::NumberHelper::NumberToString(thread, JSTaggedValue(1234567890)), *res), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + base::NumberHelper::NumberToString(thread, JSTaggedValue(1234567890)), res), 0); res = factory->NewFromASCII("100"); - ASSERT_EQ(EcmaStringAccessor::Compare( - *base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.0))), *res), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.0))), res), 0); res = factory->NewFromASCII("100.5"); - ASSERT_EQ(EcmaStringAccessor::Compare( - *base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.5))), *res), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.5))), res), 0); res = factory->NewFromASCII("100.25"); - ASSERT_EQ(EcmaStringAccessor::Compare( - *base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.25))), *res), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.25))), res), 0); res = factory->NewFromASCII("100.125"); - ASSERT_EQ(EcmaStringAccessor::Compare( - *base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.125))), *res), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.125))), res), 0); res = factory->NewFromASCII("100.6125"); - ASSERT_EQ(EcmaStringAccessor::Compare( - *base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.6125))), *res), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.6125))), res), 0); res = factory->NewFromASCII("0.0006125"); - ASSERT_EQ(EcmaStringAccessor::Compare( - *base::NumberHelper::NumberToString(thread, JSTaggedValue(double(0.0006125))), *res), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + base::NumberHelper::NumberToString(thread, JSTaggedValue(double(0.0006125))), res), 0); res = factory->NewFromASCII("-0.0006125"); - ASSERT_EQ(EcmaStringAccessor::Compare( - *base::NumberHelper::NumberToString(thread, JSTaggedValue(double(-0.0006125))), *res), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + base::NumberHelper::NumberToString(thread, JSTaggedValue(double(-0.0006125))), res), 0); res = factory->NewFromASCII("-1234567890.0006125"); - ASSERT_EQ(EcmaStringAccessor::Compare( - *base::NumberHelper::NumberToString(thread, JSTaggedValue(double(-1234567890.0006125))), *res), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + base::NumberHelper::NumberToString(thread, JSTaggedValue(double(-1234567890.0006125))), res), 0); res = factory->NewFromASCII("1234567890.0006125"); - ASSERT_EQ(EcmaStringAccessor::Compare( - *base::NumberHelper::NumberToString(thread, JSTaggedValue(double(1234567890.0006125))), *res), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + base::NumberHelper::NumberToString(thread, JSTaggedValue(double(1234567890.0006125))), res), 0); res = factory->NewFromASCII("11234567890.000612"); - ASSERT_EQ(EcmaStringAccessor::Compare( - *base::NumberHelper::NumberToString(thread, JSTaggedValue(double(11234567890.0006125))), *res), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + base::NumberHelper::NumberToString(thread, JSTaggedValue(double(11234567890.0006125))), res), 0); } } // namespace panda::test diff --git a/ecmascript/builtins/tests/builtins_object_test.cpp b/ecmascript/builtins/tests/builtins_object_test.cpp index 1d3f091c01..a607fbb6bb 100644 --- a/ecmascript/builtins/tests/builtins_object_test.cpp +++ b/ecmascript/builtins/tests/builtins_object_test.cpp @@ -840,7 +840,7 @@ HWTEST_F_L0(BuiltinsObjectTest, ToLocaleString) TestHelper::TearDownFrame(thread, prev); ASSERT_TRUE(result.IsString()); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultValue, reinterpret_cast(result.GetRawData())), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultValue, JSHandle(thread, result)), 0); } // obj.toString() @@ -859,7 +859,7 @@ HWTEST_F_L0(BuiltinsObjectTest, ToString) TestHelper::TearDownFrame(thread, prev); ASSERT_TRUE(result.IsString()); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultValue, reinterpret_cast(result.GetRawData())), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultValue, JSHandle(thread, result)), 0); // array JSHandle arr = thread->GetEcmaVM()->GetFactory()->NewJSArray(); @@ -874,7 +874,7 @@ HWTEST_F_L0(BuiltinsObjectTest, ToString) TestHelper::TearDownFrame(thread, prev); ASSERT_TRUE(resultArr.IsString()); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultArrValue, reinterpret_cast(resultArr.GetRawData())), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultArrValue, JSHandle(thread, resultArr)), 0); // string JSHandle str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("hello"); @@ -889,7 +889,7 @@ HWTEST_F_L0(BuiltinsObjectTest, ToString) TestHelper::TearDownFrame(thread, prev); ASSERT_TRUE(resultStr.IsString()); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultStrValue, reinterpret_cast(resultStr.GetRawData())), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultStrValue, JSHandle(thread, resultStr)), 0); // function JSHandle func = thread->GetEcmaVM()->GetFactory()->NewJSFunction(thread->GetEcmaVM()->GetGlobalEnv()); @@ -904,8 +904,8 @@ HWTEST_F_L0(BuiltinsObjectTest, ToString) TestHelper::TearDownFrame(thread, prev); ASSERT_TRUE(resultFunc.IsString()); - ASSERT_EQ(EcmaStringAccessor::Compare( - *resultFuncValue, reinterpret_cast(resultFunc.GetRawData())), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + resultFuncValue, JSHandle(thread, resultFunc)), 0); // error auto ecmaVM = thread->GetEcmaVM(); @@ -923,7 +923,7 @@ HWTEST_F_L0(BuiltinsObjectTest, ToString) TestHelper::TearDownFrame(thread, prev); ASSERT_TRUE(resultError.IsString()); - ASSERT_EQ(EcmaStringAccessor::Compare(*errorValue, reinterpret_cast(resultError.GetRawData())), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, errorValue, JSHandle(thread, resultError)), 0); // boolean JSHandle value(thread, JSTaggedValue::False()); @@ -940,8 +940,8 @@ HWTEST_F_L0(BuiltinsObjectTest, ToString) TestHelper::TearDownFrame(thread, prev); ASSERT_TRUE(resultBool.IsString()); - ASSERT_EQ(EcmaStringAccessor::Compare( - *resultBoolValue, reinterpret_cast(resultBool.GetRawData())), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + resultBoolValue, JSHandle(thread, resultBool)), 0); // number JSHandle resultNumValue = @@ -955,7 +955,7 @@ HWTEST_F_L0(BuiltinsObjectTest, ToString) TestHelper::TearDownFrame(thread, prev); ASSERT_TRUE(resultNum.IsString()); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultNumValue, reinterpret_cast(resultNum.GetRawData())), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultNumValue, JSHandle(thread, resultNum)), 0); } // object.valueOf() diff --git a/ecmascript/builtins/tests/builtins_reflect_test.cpp b/ecmascript/builtins/tests/builtins_reflect_test.cpp index c004beae3b..4afdb4ad0a 100644 --- a/ecmascript/builtins/tests/builtins_reflect_test.cpp +++ b/ecmascript/builtins/tests/builtins_reflect_test.cpp @@ -166,7 +166,8 @@ HWTEST_F_L0(BuiltinsReflectTest, ReflectConstruct) JSHandle taggedResult(thread, result); JSHandle refResult = JSHandle::Cast(taggedResult); JSHandle ruler = factory->NewFromASCII("ReflectConstruct"); - ASSERT_EQ(EcmaStringAccessor::Compare(EcmaString::Cast(refResult->GetValue().GetTaggedObject()), *ruler), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + JSHandle(thread, EcmaString::Cast(refResult->GetValue())), ruler), 0); TestHelper::TearDownFrame(thread, prev); } @@ -431,17 +432,17 @@ HWTEST_F_L0(BuiltinsReflectTest, ReflectOwnKeys) JSHandle resultKey0(thread, JSTaggedValue(0)); JSHandle resultValue0 = JSObject::GetProperty(thread, JSHandle(resultArray), resultKey0).GetValue(); - ASSERT_EQ(EcmaStringAccessor::Compare( - reinterpret_cast(resultValue0.GetTaggedValue().GetTaggedObject()), - reinterpret_cast(key0.GetTaggedValue().GetTaggedObject())), + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + JSHandle(resultValue0), + JSHandle(key0)), 0); // test array[1] JSHandle resultKey1(thread, JSTaggedValue(1)); JSHandle resultValue1 = JSObject::GetProperty(thread, JSHandle(resultArray), resultKey1).GetValue(); - ASSERT_EQ(EcmaStringAccessor::Compare( - reinterpret_cast(resultValue1.GetTaggedValue().GetTaggedObject()), - reinterpret_cast(key1.GetTaggedValue().GetTaggedObject())), + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + JSHandle(resultValue1), + JSHandle(key1)), 0); TestHelper::TearDownFrame(thread, prev); } diff --git a/ecmascript/builtins/tests/builtins_regexp_test.cpp b/ecmascript/builtins/tests/builtins_regexp_test.cpp index 4e987dfaa6..1d1ccd9100 100644 --- a/ecmascript/builtins/tests/builtins_regexp_test.cpp +++ b/ecmascript/builtins/tests/builtins_regexp_test.cpp @@ -96,8 +96,8 @@ HWTEST_F_L0(BuiltinsRegExpTest, RegExpConstructor1) JSHandle originalSource(thread, jsRegexp->GetOriginalSource()); uint8_t flagsBits = static_cast(jsRegexp->GetOriginalFlags().GetInt()); JSHandle originalFlags(thread, BuiltinsRegExp::FlagsBitsToString(thread, flagsBits)); - ASSERT_EQ(EcmaStringAccessor::Compare(static_cast(originalSource->GetTaggedObject()), *pattern), 0); - ASSERT_EQ(EcmaStringAccessor::Compare(static_cast(originalFlags->GetTaggedObject()), *flags), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(originalSource), pattern), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(originalFlags), flags), 0); } HWTEST_F_L0(BuiltinsRegExpTest, RegExpConstructor2) @@ -131,8 +131,8 @@ HWTEST_F_L0(BuiltinsRegExpTest, RegExpConstructor2) JSHandle originalSource(thread, jsRegexp->GetOriginalSource()); uint8_t flagsBits = static_cast(jsRegexp->GetOriginalFlags().GetInt()); JSHandle originalFlags(thread, BuiltinsRegExp::FlagsBitsToString(thread, flagsBits)); - ASSERT_EQ(EcmaStringAccessor::Compare(static_cast(originalSource->GetTaggedObject()), *pattern), 0); - ASSERT_EQ(EcmaStringAccessor::Compare(static_cast(originalFlags->GetTaggedObject()), *flags), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(originalSource), pattern), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(originalFlags), flags), 0); } HWTEST_F_L0(BuiltinsRegExpTest, RegExpConstructor3) @@ -166,8 +166,8 @@ HWTEST_F_L0(BuiltinsRegExpTest, RegExpConstructor3) JSHandle originalSource(thread, jsRegexp->GetOriginalSource()); uint8_t flagsBits = static_cast(jsRegexp->GetOriginalFlags().GetInt()); JSHandle originalFlags(thread, BuiltinsRegExp::FlagsBitsToString(thread, flagsBits)); - ASSERT_EQ(EcmaStringAccessor::Compare(static_cast(originalSource->GetTaggedObject()), *pattern1), 0); - ASSERT_EQ(EcmaStringAccessor::Compare(static_cast(originalFlags->GetTaggedObject()), *flags2), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(originalSource), pattern1), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(originalFlags), flags2), 0); } HWTEST_F_L0(BuiltinsRegExpTest, GetSource1) @@ -184,7 +184,7 @@ HWTEST_F_L0(BuiltinsRegExpTest, GetSource1) JSHandle sourceResult(JSObject::GetProperty(thread, result1Handle, source).GetValue()); JSHandle expect = thread->GetEcmaVM()->GetFactory()->NewFromASCII("(?:)"); - ASSERT_EQ(EcmaStringAccessor::Compare(static_cast(sourceResult->GetTaggedObject()), *expect), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(sourceResult), expect), 0); } HWTEST_F_L0(BuiltinsRegExpTest, GetSource2) @@ -200,7 +200,7 @@ HWTEST_F_L0(BuiltinsRegExpTest, GetSource2) JSHandle sourceResult(JSObject::GetProperty(thread, result1Handle, source).GetValue()); JSHandle expect = thread->GetEcmaVM()->GetFactory()->NewFromASCII("\\/w+"); - ASSERT_EQ(EcmaStringAccessor::Compare(static_cast(sourceResult->GetTaggedObject()), *expect), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(sourceResult), expect), 0); } HWTEST_F_L0(BuiltinsRegExpTest, Get) @@ -250,7 +250,7 @@ HWTEST_F_L0(BuiltinsRegExpTest, GetFlags) JSHandle flagsResult(JSObject::GetProperty(thread, result1Handle, flags).GetValue()); JSHandle expectResult = thread->GetEcmaVM()->GetFactory()->NewFromASCII("gimuy"); - ASSERT_EQ(EcmaStringAccessor::Compare(static_cast(flagsResult->GetTaggedObject()), *expectResult), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(flagsResult), expectResult), 0); } HWTEST_F_L0(BuiltinsRegExpTest, toString) @@ -271,8 +271,8 @@ HWTEST_F_L0(BuiltinsRegExpTest, toString) ASSERT_TRUE(toStringResult.IsString()); JSHandle toStringResultHandle(thread, toStringResult); JSHandle expectResult = thread->GetEcmaVM()->GetFactory()->NewFromASCII("/\\w+/gimuy"); - ASSERT_EQ(EcmaStringAccessor::Compare( - static_cast(toStringResultHandle->GetTaggedObject()), *expectResult), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + JSHandle(toStringResultHandle), expectResult), 0); } HWTEST_F_L0(BuiltinsRegExpTest, Exec1) @@ -310,22 +310,22 @@ HWTEST_F_L0(BuiltinsRegExpTest, Exec1) JSHandle inputHandle(JSObject::GetProperty(thread, execResult, input).GetValue()); JSHandle outputInput = JSTaggedValue::ToString(thread, inputHandle); - ASSERT_EQ(EcmaStringAccessor::Compare(*outputInput, *inputString), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputInput, inputString), 0); JSHandle zero(thread->GetEcmaVM()->GetFactory()->NewFromASCII("0")); JSHandle zeroHandle(JSObject::GetProperty(thread, execResult, zero).GetValue()); JSHandle outputZero = JSTaggedValue::ToString(thread, zeroHandle); - ASSERT_EQ(EcmaStringAccessor::Compare(*outputZero, *resultZero), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputZero, resultZero), 0); JSHandle first(thread->GetEcmaVM()->GetFactory()->NewFromASCII("1")); JSHandle oneHandle(JSObject::GetProperty(thread, execResult, first).GetValue()); JSHandle outputOne = JSTaggedValue::ToString(thread, oneHandle); - ASSERT_EQ(EcmaStringAccessor::Compare(*outputOne, *resultOne), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputOne, resultOne), 0); JSHandle second(thread->GetEcmaVM()->GetFactory()->NewFromASCII("2")); JSHandle twoHandle(JSObject::GetProperty(thread, execResult, second).GetValue()); JSHandle outputTwo = JSTaggedValue::ToString(thread, twoHandle); - ASSERT_EQ(EcmaStringAccessor::Compare(*outputTwo, *resultTwo), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputTwo, resultTwo), 0); JSHandle regexp = JSHandle::Cast(value); JSHandle lastIndexHandle(thread->GetEcmaVM()->GetFactory()->NewFromASCII("lastIndex")); @@ -368,22 +368,22 @@ HWTEST_F_L0(BuiltinsRegExpTest, Exec2) JSHandle input(thread->GetEcmaVM()->GetFactory()->NewFromASCII("input")); JSHandle inputHandle(JSObject::GetProperty(thread, execResult, input).GetValue()); JSHandle outputInput = JSTaggedValue::ToString(thread, inputHandle); - ASSERT_EQ(EcmaStringAccessor::Compare(*outputInput, *inputString), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputInput, inputString), 0); JSHandle zero(thread->GetEcmaVM()->GetFactory()->NewFromASCII("0")); JSHandle zeroHandle(JSObject::GetProperty(thread, execResult, zero).GetValue()); JSHandle outputZero = JSTaggedValue::ToString(thread, zeroHandle); - ASSERT_EQ(EcmaStringAccessor::Compare(*outputZero, *resultZero), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputZero, resultZero), 0); JSHandle first(thread->GetEcmaVM()->GetFactory()->NewFromASCII("1")); JSHandle oneHandle(JSObject::GetProperty(thread, execResult, first).GetValue()); JSHandle outputOne = JSTaggedValue::ToString(thread, oneHandle); - ASSERT_EQ(EcmaStringAccessor::Compare(*outputOne, *resultOne), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputOne, resultOne), 0); JSHandle second(thread->GetEcmaVM()->GetFactory()->NewFromASCII("2")); JSHandle twoHandle(JSObject::GetProperty(thread, execResult, second).GetValue()); JSHandle outputTwo = JSTaggedValue::ToString(thread, twoHandle); - ASSERT_EQ(EcmaStringAccessor::Compare(*outputTwo, *resultTwo), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputTwo, resultTwo), 0); JSHandle regexp = JSHandle::Cast(value); JSHandle lastIndexHandle(thread->GetEcmaVM()->GetFactory()->NewFromASCII("lastIndex")); @@ -398,7 +398,7 @@ HWTEST_F_L0(BuiltinsRegExpTest, Exec2) JSHandle four(thread->GetEcmaVM()->GetFactory()->NewFromASCII("4")); JSHandle fourHandle(JSObject::GetProperty(thread, execResult, four).GetValue()); JSHandle outputFour = JSTaggedValue::ToString(thread, fourHandle); - ASSERT_EQ(EcmaStringAccessor::Compare(*outputFour, *resultFour), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputFour, resultFour), 0); JSHandle five(thread->GetEcmaVM()->GetFactory()->NewFromASCII("5")); JSHandle fiveHandle(JSObject::GetProperty(thread, execResult, five).GetValue()); @@ -407,7 +407,7 @@ HWTEST_F_L0(BuiltinsRegExpTest, Exec2) JSHandle six(thread->GetEcmaVM()->GetFactory()->NewFromASCII("6")); JSHandle sixHandle(JSObject::GetProperty(thread, execResult, six).GetValue()); JSHandle outputSix = JSTaggedValue::ToString(thread, sixHandle); - ASSERT_EQ(EcmaStringAccessor::Compare(*outputSix, *resultSix), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputSix, resultSix), 0); } HWTEST_F_L0(BuiltinsRegExpTest, Match1) @@ -436,7 +436,7 @@ HWTEST_F_L0(BuiltinsRegExpTest, Match1) thread->GetEcmaVM()->GetFactory()->NewFromASCII("Quick Brown Fox Jumps"); JSHandle zeroHandle(JSObject::GetProperty(thread, matchResult, zero).GetValue()); JSHandle outputZero = JSTaggedValue::ToString(thread, zeroHandle); - ASSERT_EQ(EcmaStringAccessor::Compare(*outputZero, *resultZero), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputZero, resultZero), 0); } HWTEST_F_L0(BuiltinsRegExpTest, Test1) @@ -508,7 +508,7 @@ HWTEST_F_L0(BuiltinsRegExpTest, Split1) JSHandle zeroHandle(JSObject::GetProperty(thread, splitResult, zero).GetValue()); JSHandle outputZero = JSTaggedValue::ToString(thread, zeroHandle); - ASSERT_EQ(EcmaStringAccessor::Compare(*outputZero, *inputString), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputZero, inputString), 0); } HWTEST_F_L0(BuiltinsRegExpTest, Split2) @@ -538,17 +538,17 @@ HWTEST_F_L0(BuiltinsRegExpTest, Split2) JSHandle zero(thread->GetEcmaVM()->GetFactory()->NewFromASCII("0")); JSHandle zeroHandle(JSObject::GetProperty(thread, splitResult, zero).GetValue()); JSHandle outputZero = JSTaggedValue::ToString(thread, zeroHandle); - ASSERT_EQ(EcmaStringAccessor::Compare(*outputZero, *resultZero), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputZero, resultZero), 0); JSHandle first(thread->GetEcmaVM()->GetFactory()->NewFromASCII("1")); JSHandle oneHandle(JSObject::GetProperty(thread, splitResult, first).GetValue()); JSHandle outputOne = JSTaggedValue::ToString(thread, oneHandle); - ASSERT_EQ(EcmaStringAccessor::Compare(*outputOne, *resultOne), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputOne, resultOne), 0); JSHandle second(thread->GetEcmaVM()->GetFactory()->NewFromASCII("2")); JSHandle twoHandle(JSObject::GetProperty(thread, splitResult, second).GetValue()); JSHandle outputTwo = JSTaggedValue::ToString(thread, twoHandle); - ASSERT_EQ(EcmaStringAccessor::Compare(*outputTwo, *resultTwo), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputTwo, resultTwo), 0); } HWTEST_F_L0(BuiltinsRegExpTest, GetSpecies) @@ -590,7 +590,7 @@ HWTEST_F_L0(BuiltinsRegExpTest, Replace1) JSHandle replaceResult(thread, results); JSHandle resultZero = thread->GetEcmaVM()->GetFactory()->NewFromASCII( "The Quick Brown Fox Jumpsa The Over The Lazy Dog Jumps Brown $1 Jumps1 $32 a Over The Lazy Dog"); - ASSERT_EQ(EcmaStringAccessor::Compare(static_cast(replaceResult->GetTaggedObject()), *resultZero), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(replaceResult), resultZero), 0); } HWTEST_F_L0(BuiltinsRegExpTest, Replace2) @@ -615,7 +615,7 @@ HWTEST_F_L0(BuiltinsRegExpTest, Replace2) JSTaggedValue results = BuiltinsRegExp::Replace(ecmaRuntimeCallInfo); JSHandle replaceResult(thread, results); JSHandle resultZero = factory->NewFromASCII("a[cd$04$00]e"); - ASSERT_EQ(EcmaStringAccessor::Compare(static_cast(replaceResult->GetTaggedObject()), *resultZero), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(replaceResult), resultZero), 0); } HWTEST_F_L0(BuiltinsRegExpTest, Replace3) @@ -640,7 +640,7 @@ HWTEST_F_L0(BuiltinsRegExpTest, Replace3) JSTaggedValue results = BuiltinsRegExp::Replace(ecmaRuntimeCallInfo); JSHandle replaceResult(thread, results); JSHandle resultZero = factory->NewFromASCII("de"); - ASSERT_EQ(EcmaStringAccessor::Compare(static_cast(replaceResult->GetTaggedObject()), *resultZero), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(replaceResult), resultZero), 0); } HWTEST_F_L0(BuiltinsRegExpTest, RegExpParseCache) diff --git a/ecmascript/builtins/tests/builtins_string_test.cpp b/ecmascript/builtins/tests/builtins_string_test.cpp index cf1be77df9..6224073d9e 100644 --- a/ecmascript/builtins/tests/builtins_string_test.cpp +++ b/ecmascript/builtins/tests/builtins_string_test.cpp @@ -108,10 +108,9 @@ HWTEST_F_L0(BuiltinsStringTest, StringConstructor1) JSTaggedValue value(static_cast(result.GetRawData())); ASSERT_TRUE(value.IsECMAObject()); JSHandle ref(thread, JSPrimitiveRef::Cast(value.GetTaggedObject())); - JSTaggedValue test = factory->NewFromASCII("ABC").GetTaggedValue(); - ASSERT_EQ(EcmaStringAccessor::Compare(EcmaString::Cast(ref->GetValue().GetTaggedObject()), - reinterpret_cast(test.GetRawData())), - 0); + JSHandle test = factory->NewFromASCII("ABC"); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, + JSHandle(thread, EcmaString::Cast(ref->GetValue())), test), 0); } // String.fromCharCode(65, 66, 67) @@ -134,10 +133,8 @@ HWTEST_F_L0(BuiltinsStringTest, fromCharCode1) ASSERT_TRUE(result.IsString()); JSTaggedValue value(static_cast(result.GetRawData())); JSHandle valueHandle(thread, JSTaggedValue(value.GetTaggedObject())); - JSTaggedValue test = factory->NewFromASCII("ABC").GetTaggedValue(); - ASSERT_EQ(EcmaStringAccessor::Compare(EcmaString::Cast(valueHandle->GetTaggedObject()), - reinterpret_cast(test.GetRawData())), - 0); + JSHandle test = factory->NewFromASCII("ABC"); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle::Cast(valueHandle), test), 0); } // String.fromCodePoint(65, 66, 67) @@ -159,8 +156,8 @@ HWTEST_F_L0(BuiltinsStringTest, fromCodePoint1) JSTaggedValue result = BuiltinsString::FromCodePoint(ecmaRuntimeCallInfo); ASSERT_TRUE(result.IsString()); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); - JSTaggedValue test = factory->NewFromASCII("ABC").GetTaggedValue(); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast(test.GetRawData())), 0); + JSHandle test = factory->NewFromASCII("ABC"); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0); } // "abcabcabc".charAt(5) @@ -178,8 +175,8 @@ HWTEST_F_L0(BuiltinsStringTest, charAt1) JSTaggedValue result = BuiltinsString::CharAt(ecmaRuntimeCallInfo); ASSERT_TRUE(result.IsString()); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); - JSTaggedValue test = factory->NewFromASCII("c").GetTaggedValue(); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast(test.GetRawData())), 0); + JSHandle test = factory->NewFromASCII("c"); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0); } // "一二三四".charAt(2) @@ -197,8 +194,8 @@ HWTEST_F_L0(BuiltinsStringTest, charAt2) JSTaggedValue result = BuiltinsString::CharAt(ecmaRuntimeCallInfo); ASSERT_TRUE(result.IsString()); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); - JSTaggedValue test = factory->NewFromUtf8("三").GetTaggedValue(); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast(test.GetRawData())), 0); + JSHandle test = factory->NewFromUtf8("三"); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0); } // "abcabcabc".charAt(-1) @@ -216,8 +213,8 @@ HWTEST_F_L0(BuiltinsStringTest, charAt3) JSTaggedValue result = BuiltinsString::CharAt(ecmaRuntimeCallInfo); ASSERT_TRUE(result.IsString()); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); - JSTaggedValue test = factory->GetEmptyString().GetTaggedValue(); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast(test.GetRawData())), 0); + JSHandle test = factory->GetEmptyString(); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0); } // "ABC".charCodeAt(0) @@ -292,8 +289,8 @@ HWTEST_F_L0(BuiltinsStringTest, concat1) JSTaggedValue result = BuiltinsString::Concat(ecmaRuntimeCallInfo); ASSERT_TRUE(result.IsString()); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); - JSTaggedValue test = factory->NewFromASCII("abcd").GetTaggedValue(); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast(test.GetRawData())), 0); + JSHandle test = factory->NewFromASCII("abcd"); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0); } // "abcabcabc".indexof('b') @@ -585,8 +582,8 @@ HWTEST_F_L0(BuiltinsStringTest, toLocaleLowerCase2) JSTaggedValue result = BuiltinsString::ToLocaleLowerCase(ecmaRuntimeCallInfo); ASSERT_TRUE(result.IsString()); JSHandle result_handle(thread, reinterpret_cast(result.GetRawData())); - JSTaggedValue test = factory->NewFromUtf8("有abc").GetTaggedValue(); - ASSERT_EQ(EcmaStringAccessor::Compare(*result_handle, reinterpret_cast(test.GetRawData())), 0); + JSHandle test = factory->NewFromUtf8("有abc"); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, result_handle, test), 0); } // "ABC".toLowerCase() @@ -621,8 +618,8 @@ HWTEST_F_L0(BuiltinsStringTest, toUpperCase1) JSTaggedValue result = BuiltinsString::ToUpperCase(ecmaRuntimeCallInfo); ASSERT_TRUE(result.IsString()); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); - JSTaggedValue test = factory->NewFromASCII("ABC").GetTaggedValue(); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast(test.GetRawData())), 0); + JSHandle test = factory->NewFromASCII("ABC"); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0); } // "abc".localecompare('b') @@ -719,8 +716,8 @@ HWTEST_F_L0(BuiltinsStringTest, normalize1) JSTaggedValue result = BuiltinsString::Normalize(ecmaRuntimeCallInfo); ASSERT_TRUE(result.IsString()); JSHandle result_handle(thread, reinterpret_cast(result.GetRawData())); - JSTaggedValue test = factory->NewFromASCII("abc").GetTaggedValue(); - ASSERT_EQ(EcmaStringAccessor::Compare(*result_handle, reinterpret_cast(test.GetRawData())), 0); + JSHandle test = factory->NewFromASCII("abc"); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, result_handle, test), 0); } // "abc".repeat(5) @@ -738,8 +735,8 @@ HWTEST_F_L0(BuiltinsStringTest, repeat1) JSTaggedValue result = BuiltinsString::Repeat(ecmaRuntimeCallInfo); ASSERT_TRUE(result.IsString()); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); - JSTaggedValue test = factory->NewFromASCII("abcabcabcabcabc").GetTaggedValue(); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast(test.GetRawData())), 0); + JSHandle test = factory->NewFromASCII("abcabcabcabcabc"); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0); } // 'The morning is upon us.'.slice(4, -2) @@ -758,8 +755,8 @@ HWTEST_F_L0(BuiltinsStringTest, slice1) JSTaggedValue result = BuiltinsString::Slice(ecmaRuntimeCallInfo); ASSERT_TRUE(result.IsString()); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); - JSTaggedValue test = factory->NewFromASCII("morning is upon u").GetTaggedValue(); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast(test.GetRawData())), 0); + JSHandle test = factory->NewFromASCII("morning is upon u"); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0); } // 'The morning is upon us.'.slice(12) @@ -777,8 +774,8 @@ HWTEST_F_L0(BuiltinsStringTest, slice2) JSTaggedValue result = BuiltinsString::Slice(ecmaRuntimeCallInfo); ASSERT_TRUE(result.IsString()); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); - JSTaggedValue test = factory->NewFromASCII("is upon us.").GetTaggedValue(); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast(test.GetRawData())), 0); + JSHandle test = factory->NewFromASCII("is upon us."); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0); } // 'Mozilla'.substring(3, -3) @@ -797,8 +794,8 @@ HWTEST_F_L0(BuiltinsStringTest, substring1) JSTaggedValue result = BuiltinsString::Substring(ecmaRuntimeCallInfo); ASSERT_TRUE(result.IsString()); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); - JSTaggedValue test = factory->NewFromASCII("Moz").GetTaggedValue(); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast(test.GetRawData())), 0); + JSHandle test = factory->NewFromASCII("Moz"); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0); } // 'Mozilla'.substring(7, 4) @@ -817,8 +814,8 @@ HWTEST_F_L0(BuiltinsStringTest, substring2) JSTaggedValue result = BuiltinsString::Substring(ecmaRuntimeCallInfo); ASSERT_TRUE(result.IsString()); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); - JSTaggedValue test = factory->NewFromASCII("lla").GetTaggedValue(); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast(test.GetRawData())), 0); + JSHandle test = factory->NewFromASCII("lla"); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0); } // " Hello world! ".trim() @@ -835,8 +832,8 @@ HWTEST_F_L0(BuiltinsStringTest, trim1) JSTaggedValue result = BuiltinsString::Trim(ecmaRuntimeCallInfo); ASSERT_TRUE(result.IsString()); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); - JSTaggedValue test = factory->NewFromASCII("Hello world!").GetTaggedValue(); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast(test.GetRawData())), 0); + JSHandle test = factory->NewFromASCII("Hello world!"); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0); } HWTEST_F_L0(BuiltinsStringTest, trim2) @@ -858,8 +855,8 @@ HWTEST_F_L0(BuiltinsStringTest, trim2) JSTaggedValue result = BuiltinsString::Trim(ecmaRuntimeCallInfo); ASSERT_TRUE(result.IsString()); JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); - JSTaggedValue test = factory->NewFromASCII("Hello world!").GetTaggedValue(); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast(test.GetRawData())), 0); + JSHandle test = factory->NewFromASCII("Hello world!"); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0); } HWTEST_F_L0(BuiltinsStringTest, ToString) diff --git a/ecmascript/builtins/tests/builtins_symbol_test.cpp b/ecmascript/builtins/tests/builtins_symbol_test.cpp index 9be8335e22..f4c744f28a 100644 --- a/ecmascript/builtins/tests/builtins_symbol_test.cpp +++ b/ecmascript/builtins/tests/builtins_symbol_test.cpp @@ -81,8 +81,8 @@ HWTEST_F_L0(BuiltinsSymbolTest, SymbolNoParameterToString) JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); ASSERT_TRUE(result.IsString()); - auto symbolValue = ecmascript::base::BuiltinsBase::GetTaggedString(thread, "Symbol()"); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast(symbolValue.GetRawData()), *resultHandle), 0); + auto symbolValue = ecmaVM->GetFactory()->NewFromASCII("Symbol()"); + ASSERT_EQ(EcmaStringAccessor::Compare(ecmaVM, symbolValue, resultHandle), 0); } // new Symbol("aaa").toString() @@ -101,8 +101,8 @@ HWTEST_F_L0(BuiltinsSymbolTest, SymbolWithParameterToString) JSHandle resultHandle(thread, reinterpret_cast(result.GetRawData())); ASSERT_TRUE(result.IsString()); - auto symbolValue = ecmascript::base::BuiltinsBase::GetTaggedString(thread, "Symbol(aaa)"); - ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast(symbolValue.GetRawData()), *resultHandle), 0); + auto symbolValue = ecmaVM->GetFactory()->NewFromASCII("Symbol(aaa)"); + ASSERT_EQ(EcmaStringAccessor::Compare(ecmaVM, symbolValue, resultHandle), 0); } // new Symbol().valueOf() @@ -307,7 +307,7 @@ HWTEST_F_L0(BuiltinsSymbolTest, SymbolConstructor) TestHelper::TearDownFrame(thread, prev); JSHandle resultString = JSTaggedValue::ToString( thread, JSHandle(thread, reinterpret_cast(result1.GetRawData())->GetDescription())); - ASSERT_EQ(EcmaStringAccessor::Compare(*resultString, *string), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(ecmaVM, resultString, string), 0); } HWTEST_F_L0(BuiltinsSymbolTest, SymbolGetter) diff --git a/ecmascript/compiler/builtins/builtins_string_stub_builder.cpp b/ecmascript/compiler/builtins/builtins_string_stub_builder.cpp index f8e2fd7998..2dbcab4c41 100644 --- a/ecmascript/compiler/builtins/builtins_string_stub_builder.cpp +++ b/ecmascript/compiler/builtins/builtins_string_stub_builder.cpp @@ -32,7 +32,7 @@ GateRef BuiltinsStringStubBuilder::StringAt(GateRef obj, GateRef index) Label doIntOp(env); Label leftIsNumber(env); Label rightIsNumber(env); - GateRef dataUtf16 = PtrAdd(obj, IntPtr(EcmaString::DATA_OFFSET)); + GateRef dataUtf16 = PtrAdd(obj, IntPtr(LineEcmaString::DATA_OFFSET)); Branch(IsUtf16String(obj), &isUtf16, &isUtf8); Bind(&isUtf16); { @@ -65,7 +65,7 @@ GateRef BuiltinsStringStubBuilder::CreateFromEcmaString(GateRef glue, GateRef ob Label isUtf16(env); Label isUtf8(env); Label allocString(env); - GateRef dataUtf = PtrAdd(obj, IntPtr(EcmaString::DATA_OFFSET)); + GateRef dataUtf = PtrAdd(obj, IntPtr(LineEcmaString::DATA_OFFSET)); Branch(IsUtf16String(obj), &isUtf16, &isUtf8); Bind(&isUtf16); { @@ -91,17 +91,17 @@ GateRef BuiltinsStringStubBuilder::CreateFromEcmaString(GateRef glue, GateRef ob Branch(*canBeCompressed, &isUtf8Next, &isUtf16Next); Bind(&isUtf8Next); { - newBuilder.AllocStringObject(&result, &afterNew, Int32(1), true); + newBuilder.AllocLineStringObject(&result, &afterNew, Int32(1), true); } Bind(&isUtf16Next); { - newBuilder.AllocStringObject(&result, &afterNew, Int32(1), false); + newBuilder.AllocLineStringObject(&result, &afterNew, Int32(1), false); } Bind(&afterNew); { Label isUtf8Copy(env); Label isUtf16Copy(env); - GateRef dst = PtrAdd(*result, IntPtr(EcmaString::DATA_OFFSET)); + GateRef dst = PtrAdd(*result, IntPtr(LineEcmaString::DATA_OFFSET)); Branch(*canBeCompressed, &isUtf8Copy, &isUtf16Copy); Bind(&isUtf8Copy); { @@ -144,12 +144,12 @@ GateRef BuiltinsStringStubBuilder::FastSubUtf8String(GateRef glue, GateRef thisV NewObjectStubBuilder newBuilder(this); newBuilder.SetParameters(glue, 0); Label afterNew(env); - newBuilder.AllocStringObject(&result, &afterNew, len, true); + newBuilder.AllocLineStringObject(&result, &afterNew, len, true); Bind(&afterNew); { - GateRef dst = PtrAdd(*result, IntPtr(EcmaString::DATA_OFFSET)); - GateRef source = PtrAdd(PtrAdd(thisValue, IntPtr(EcmaString::DATA_OFFSET)), ZExtInt32ToPtr(from)); - StringCopy(glue, dst, source, len, IntPtr(sizeof(uint8_t)), VariableType::INT8()); + GateRef dst = PtrAdd(*result, IntPtr(LineEcmaString::DATA_OFFSET)); + GateRef source = PtrAdd(PtrAdd(thisValue, IntPtr(LineEcmaString::DATA_OFFSET)), ZExtInt32ToPtr(from)); + CopyChars(glue, dst, source, len, IntPtr(sizeof(uint8_t)), VariableType::INT8()); Jump(&exit); } } @@ -184,7 +184,7 @@ GateRef BuiltinsStringStubBuilder::FastSubUtf16String(GateRef glue, GateRef this Bind(&lenNotEqualZero); { GateRef fromOffset = PtrMul(ZExtInt32ToPtr(from), IntPtr(sizeof(uint16_t) / sizeof(uint8_t))); - GateRef source = PtrAdd(PtrAdd(thisValue, IntPtr(EcmaString::DATA_OFFSET)), fromOffset); + GateRef source = PtrAdd(PtrAdd(thisValue, IntPtr(LineEcmaString::DATA_OFFSET)), fromOffset); GateRef canBeCompressed = CanBeCompressed(source, len, true); NewObjectStubBuilder newBuilder(this); newBuilder.SetParameters(glue, 0); @@ -192,16 +192,16 @@ GateRef BuiltinsStringStubBuilder::FastSubUtf16String(GateRef glue, GateRef this Branch(canBeCompressed, &isUtf8, &isUtf16); Bind(&isUtf8); { - newBuilder.AllocStringObject(&result, &afterNew, len, true); + newBuilder.AllocLineStringObject(&result, &afterNew, len, true); } Bind(&isUtf16); { - newBuilder.AllocStringObject(&result, &afterNew, len, false); + newBuilder.AllocLineStringObject(&result, &afterNew, len, false); } Bind(&afterNew); { - GateRef source1 = PtrAdd(PtrAdd(thisValue, IntPtr(EcmaString::DATA_OFFSET)), fromOffset); - GateRef dst = PtrAdd(*result, IntPtr(EcmaString::DATA_OFFSET)); + GateRef source1 = PtrAdd(PtrAdd(thisValue, IntPtr(LineEcmaString::DATA_OFFSET)), fromOffset); + GateRef dst = PtrAdd(*result, IntPtr(LineEcmaString::DATA_OFFSET)); Branch(canBeCompressed, &isUtf8Next, &isUtf16Next); Bind(&isUtf8Next); { @@ -210,7 +210,7 @@ GateRef BuiltinsStringStubBuilder::FastSubUtf16String(GateRef glue, GateRef this } Bind(&isUtf16Next); { - StringCopy(glue, dst, source1, len, IntPtr(sizeof(uint16_t)), VariableType::INT16()); + CopyChars(glue, dst, source1, len, IntPtr(sizeof(uint16_t)), VariableType::INT16()); Jump(&exit); } } @@ -221,7 +221,7 @@ GateRef BuiltinsStringStubBuilder::FastSubUtf16String(GateRef glue, GateRef this return ret; } -void BuiltinsStringStubBuilder::StringCopy(GateRef glue, GateRef dst, GateRef source, +void BuiltinsStringStubBuilder::CopyChars(GateRef glue, GateRef dst, GateRef source, GateRef sourceLength, GateRef size, VariableType type) { auto env = GetEnvironment(); @@ -520,8 +520,8 @@ GateRef BuiltinsStringStubBuilder::StringIndexOf(GateRef lhs, GateRef rhs, GateR Branch(Int32LessThan(max, Int32(0)), &exit, &maxNotLessZero); Bind(&maxNotLessZero); { - GateRef rhsData = PtrAdd(rhs, IntPtr(EcmaString::DATA_OFFSET)); - GateRef lhsData = PtrAdd(lhs, IntPtr(EcmaString::DATA_OFFSET)); + GateRef rhsData = PtrAdd(rhs, IntPtr(LineEcmaString::DATA_OFFSET)); + GateRef lhsData = PtrAdd(lhs, IntPtr(LineEcmaString::DATA_OFFSET)); Branch(IsUtf8String(rhs), &rhsIsUtf8, &rhsIsUtf16); Bind(&rhsIsUtf8); { diff --git a/ecmascript/compiler/builtins/builtins_string_stub_builder.h b/ecmascript/compiler/builtins/builtins_string_stub_builder.h index 59976ee86f..e2bc6ebe99 100644 --- a/ecmascript/compiler/builtins/builtins_string_stub_builder.h +++ b/ecmascript/compiler/builtins/builtins_string_stub_builder.h @@ -30,7 +30,7 @@ public: GateRef StringAt(GateRef obj, GateRef index); GateRef FastSubUtf8String(GateRef glue, GateRef thisValue, GateRef from, GateRef len); GateRef FastSubUtf16String(GateRef glue, GateRef thisValue, GateRef from, GateRef len); - void StringCopy(GateRef glue, GateRef dst, GateRef source, GateRef sourceLength, GateRef size, VariableType type); + void CopyChars(GateRef glue, GateRef dst, GateRef source, GateRef sourceLength, GateRef size, VariableType type); void CopyUtf16AsUtf8(GateRef glue, GateRef src, GateRef dst, GateRef sourceLength); GateRef StringIndexOf(GateRef lhsData, bool lhsIsUtf8, GateRef rhsData, bool rhsIsUtf8, GateRef pos, GateRef max, GateRef rhsCount); diff --git a/ecmascript/compiler/circuit_builder-inl.h b/ecmascript/compiler/circuit_builder-inl.h index f739bc8369..5708cf2af4 100644 --- a/ecmascript/compiler/circuit_builder-inl.h +++ b/ecmascript/compiler/circuit_builder-inl.h @@ -593,9 +593,17 @@ GateRef CircuitBuilder::IsJSObject(GateRef obj) return LogicAnd(TaggedIsHeapObject(obj), ret); } +GateRef CircuitBuilder::TaggedObjectIsString(GateRef obj) +{ + GateRef objectType = GetObjectType(LoadHClass(obj)); + return BoolAnd( + Int32LessThanOrEqual(objectType, Int32(static_cast(JSType::STRING_LAST))), + Int32GreaterThanOrEqual(objectType, Int32(static_cast(JSType::STRING_FIRST)))); +} + GateRef CircuitBuilder::TaggedObjectBothAreString(GateRef x, GateRef y) { - return BoolAnd(IsJsType(x, JSType::STRING), IsJsType(y, JSType::STRING)); + return BoolAnd(TaggedObjectIsString(x), TaggedObjectIsString(y)); } GateRef CircuitBuilder::IsCallableFromBitField(GateRef bitfield) diff --git a/ecmascript/compiler/circuit_builder.cpp b/ecmascript/compiler/circuit_builder.cpp index 3841a4aba7..1bd561966c 100644 --- a/ecmascript/compiler/circuit_builder.cpp +++ b/ecmascript/compiler/circuit_builder.cpp @@ -534,8 +534,7 @@ GateRef CircuitBuilder::TaggedIsString(GateRef obj) Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit); Bind(&isHeapObject); { - result = Equal(GetObjectType(LoadHClass(obj)), - Int32(static_cast(JSType::STRING))); + result = TaggedObjectIsString(obj); Jump(&exit); } Bind(&exit); @@ -554,13 +553,13 @@ GateRef CircuitBuilder::TaggedIsStringOrSymbol(GateRef obj) Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit); Bind(&isHeapObject); { - GateRef objType = GetObjectType(LoadHClass(obj)); - result = Equal(objType, Int32(static_cast(JSType::STRING))); + result = TaggedObjectIsString(obj); Label isString(env_); Label notString(env_); Branch(*result, &exit, ¬String); Bind(¬String); { + GateRef objType = GetObjectType(LoadHClass(obj)); result = Equal(objType, Int32(static_cast(JSType::SYMBOL))); Jump(&exit); } @@ -691,6 +690,31 @@ GateRef CircuitBuilder::GetObjectFromConstPool(GateRef glue, GateRef constPool, return ret; } +GateRef CircuitBuilder::TryGetHashcodeFromString(GateRef string) +{ + Label subentry(env_); + SubCfgEntry(&subentry); + Label noRawHashcode(env_); + Label storeHash(env_); + Label exit(env_); + DEFVAlUE(result, env_, VariableType::INT64(), Int64(-1)); + GateRef hashCode = ZExtInt32ToInt64(Load(VariableType::INT32(), string, IntPtr(EcmaString::HASHCODE_OFFSET))); + Branch(Int64Equal(hashCode, Int64(0)), &noRawHashcode, &storeHash); + Bind(&noRawHashcode); + { + GateRef length = GetLengthFromString(string); + Label lengthNotZero(env_); + Branch(Int32Equal(length, Int32(0)), &storeHash, &exit); + } + Bind(&storeHash); + result = hashCode; + Jump(&exit); + Bind(&exit); + auto ret = *result; + SubCfgExit(); + return ret; +} + GateRef CircuitBuilder::GetHashcodeFromString(GateRef glue, GateRef value) { Label subentry(env_); diff --git a/ecmascript/compiler/circuit_builder.h b/ecmascript/compiler/circuit_builder.h index 36c03b7393..666003e722 100644 --- a/ecmascript/compiler/circuit_builder.h +++ b/ecmascript/compiler/circuit_builder.h @@ -434,6 +434,7 @@ public: inline GateRef IsExtensible(GateRef object); inline GateRef TaggedObjectIsEcmaObject(GateRef obj); inline GateRef IsJSObject(GateRef obj); + inline GateRef TaggedObjectIsString(GateRef obj); inline GateRef TaggedObjectBothAreString(GateRef x, GateRef y); inline GateRef IsCallable(GateRef obj); inline GateRef IsCallableFromBitField(GateRef bitfield); @@ -448,6 +449,7 @@ public: GateRef FunctionIsResolved(GateRef function); GateRef GetLengthFromString(GateRef value); GateRef GetHashcodeFromString(GateRef glue, GateRef value); + GateRef TryGetHashcodeFromString(GateRef string); GateRef IsUtf16String(GateRef string); GateRef TaggedIsBigInt(GateRef obj); void SetLexicalEnvToFunction(GateRef glue, GateRef function, GateRef value); diff --git a/ecmascript/compiler/common_stubs.cpp b/ecmascript/compiler/common_stubs.cpp index c4d91f07eb..d412c54b9a 100644 --- a/ecmascript/compiler/common_stubs.cpp +++ b/ecmascript/compiler/common_stubs.cpp @@ -324,7 +324,7 @@ void TryLoadICByValueStubBuilder::GenerateCircuit() &hclassEqualFirstValue, &hclassNotEqualFirstValue); Bind(&hclassEqualFirstValue); - Return(LoadElement(receiver, key)); + Return(LoadElement(glue, receiver, key)); Bind(&hclassNotEqualFirstValue); { Branch(Int64Equal(firstValue, key), &firstValueEqualKey, &receiverNotHeapObject); diff --git a/ecmascript/compiler/ic_stub_builder.cpp b/ecmascript/compiler/ic_stub_builder.cpp index d2a569486b..40b2079ebf 100644 --- a/ecmascript/compiler/ic_stub_builder.cpp +++ b/ecmascript/compiler/ic_stub_builder.cpp @@ -145,7 +145,7 @@ void ICStubBuilder::LoadICByValue(Variable* result, Label* tryFastPath, Label *s ValuedICAccessor(&cachedHandler, &loadWithHandler, &loadElement); Bind(&loadElement); { - GateRef ret = LoadElement(receiver_, propKey_); + GateRef ret = LoadElement(glue_, receiver_, propKey_); result->WriteVariable(ret); Branch(TaggedIsHole(ret), slowPath_, success_); } diff --git a/ecmascript/compiler/new_object_stub_builder.cpp b/ecmascript/compiler/new_object_stub_builder.cpp index 2f4ab2a410..50d9687ce1 100644 --- a/ecmascript/compiler/new_object_stub_builder.cpp +++ b/ecmascript/compiler/new_object_stub_builder.cpp @@ -283,7 +283,7 @@ void NewObjectStubBuilder::InitializeTaggedArrayWithSpeicalValue(Label *exit, InitializeWithSpeicalValue(exit, array, value, dataOffset, endOffset); } -void NewObjectStubBuilder::AllocStringObject(Variable *result, Label *exit, GateRef length, bool compressed) +void NewObjectStubBuilder::AllocLineStringObject(Variable *result, Label *exit, GateRef length, bool compressed) { auto env = GetEnvironment(); if (compressed) { @@ -297,9 +297,9 @@ void NewObjectStubBuilder::AllocStringObject(Variable *result, Label *exit, Gate AllocateInYoung(result, &afterAllocate); Bind(&afterAllocate); - GateRef arrayClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, - ConstantIndex::STRING_CLASS_INDEX); - StoreHClass(glue_, result->ReadVariable(), arrayClass); + GateRef stringClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, + ConstantIndex::LINE_STRING_CLASS_INDEX); + StoreHClass(glue_, result->ReadVariable(), stringClass); SetLength(glue_, result->ReadVariable(), length, compressed); SetRawHashcode(glue_, result->ReadVariable(), Int32(0)); Jump(exit); diff --git a/ecmascript/compiler/new_object_stub_builder.h b/ecmascript/compiler/new_object_stub_builder.h index 219e6198e4..960a20945c 100644 --- a/ecmascript/compiler/new_object_stub_builder.h +++ b/ecmascript/compiler/new_object_stub_builder.h @@ -39,7 +39,7 @@ public: void NewJSObject(Variable *result, Label *exit, GateRef hclass); void NewArgumentsList(Variable *result, Label *exit, GateRef sp, GateRef startIdx, GateRef numArgs); void NewArgumentsObj(Variable *result, Label *exit, GateRef argumentsList, GateRef numArgs); - void AllocStringObject(Variable *result, Label *exit, GateRef length, bool compressed); + void AllocLineStringObject(Variable *result, Label *exit, GateRef length, bool compressed); void HeapAlloc(Variable *result, Label *exit, RegionSpaceFlag spaceType); void NewJSArrayLiteral(Variable *result, Label *exit, RegionSpaceFlag spaceType, GateRef obj, GateRef hclass, bool isEmptyArray); diff --git a/ecmascript/compiler/slowpath_lowering.cpp b/ecmascript/compiler/slowpath_lowering.cpp index ea748c6970..8c654878f7 100644 --- a/ecmascript/compiler/slowpath_lowering.cpp +++ b/ecmascript/compiler/slowpath_lowering.cpp @@ -1692,9 +1692,17 @@ GateRef SlowPathLowering::FastStrictEqual(GateRef glue, GateRef left, GateRef ri builder_.Branch(builder_.Equal(builder_.GetLengthFromString(left), builder_.GetLengthFromString(right)), &hashcodeCompare, &exit); builder_.Bind(&hashcodeCompare); - builder_.Branch( - builder_.Equal(builder_.GetHashcodeFromString(glue, left), builder_.GetHashcodeFromString(glue, right)), - &contentsCompare, &exit); + Label leftNotNeg(&builder_); + GateRef leftHash = builder_.TryGetHashcodeFromString(left); + GateRef rightHash = builder_.TryGetHashcodeFromString(right); + builder_.Branch(builder_.Equal(leftHash, builder_.Int64(-1)), &contentsCompare, &leftNotNeg); + builder_.Bind(&leftNotNeg); + { + Label rightNotNeg(&builder_); + builder_.Branch(builder_.Equal(rightHash, builder_.Int64(-1)), &contentsCompare, &rightNotNeg); + builder_.Bind(&rightNotNeg); + builder_.Branch(builder_.Equal(leftHash, rightHash), &contentsCompare, &exit); + } builder_.Bind(&contentsCompare); { GateRef stringEqual = LowerCallRuntime(glue, RTSTUB_ID(StringEqual), { left, right }, true); @@ -3108,7 +3116,7 @@ void SlowPathLowering::LowerTypeof(GateRef gate, GateRef glue) { Label objIsString(&builder_); Label objNotString(&builder_); - builder_.Branch(builder_.IsJsType(obj, JSType::STRING), &objIsString, &objNotString); + builder_.Branch(builder_.TaggedObjectIsString(obj), &objIsString, &objNotString); builder_.Bind(&objIsString); { result = builder_.Load(VariableType::JS_POINTER(), gConstAddr, diff --git a/ecmascript/compiler/stub_builder-inl.h b/ecmascript/compiler/stub_builder-inl.h index 81b5fbdec4..79795d1721 100644 --- a/ecmascript/compiler/stub_builder-inl.h +++ b/ecmascript/compiler/stub_builder-inl.h @@ -1011,9 +1011,27 @@ inline GateRef StubBuilder::IsSymbol(GateRef obj) } inline GateRef StubBuilder::IsString(GateRef obj) +{ + return env_->GetBuilder()->TaggedObjectIsString(obj); +} + +inline GateRef StubBuilder::IsLineString(GateRef obj) { GateRef objectType = GetObjectType(LoadHClass(obj)); - return Int32Equal(objectType, Int32(static_cast(JSType::STRING))); + return Int32Equal(objectType, Int32(static_cast(JSType::LINE_STRING))); +} + +inline GateRef StubBuilder::IsTreeString(GateRef obj) +{ + GateRef objectType = GetObjectType(LoadHClass(obj)); + return Int32Equal(objectType, Int32(static_cast(JSType::TREE_STRING))); +} + +inline GateRef StubBuilder::TreeStringIsFlat(GateRef string) +{ + GateRef second = GetSecondFromTreeString(string); + GateRef len = GetLengthFromString(second); + return Int32Equal(len, Int32(0)); } inline GateRef StubBuilder::TaggedObjectIsBigInt(GateRef obj) @@ -1336,6 +1354,18 @@ inline GateRef StubBuilder::GetLengthFromString(GateRef value) return Int32LSR(len, Int32(2)); // 2 : 2 means len must be right shift 2 bits } +inline GateRef StubBuilder::GetFirstFromTreeString(GateRef string) +{ + GateRef offset = IntPtr(TreeEcmaString::FIRST_OFFSET); + return Load(VariableType::JS_POINTER(), string, offset); +} + +inline GateRef StubBuilder::GetSecondFromTreeString(GateRef string) +{ + GateRef offset = IntPtr(TreeEcmaString::SECOND_OFFSET); + return Load(VariableType::JS_POINTER(), string, offset); +} + inline void StubBuilder::SetBitFieldToHClass(GateRef glue, GateRef hClass, GateRef bitfield) { GateRef offset = IntPtr(JSHClass::BIT_FIELD_OFFSET); @@ -1999,12 +2029,12 @@ inline GateRef StubBuilder::GetBuiltinId(GateRef method) inline GateRef StubBuilder::ComputeSizeUtf8(GateRef length) { - return PtrAdd(IntPtr(EcmaString::DATA_OFFSET), length); + return PtrAdd(IntPtr(LineEcmaString::DATA_OFFSET), length); } inline GateRef StubBuilder::ComputeSizeUtf16(GateRef length) { - return PtrAdd(IntPtr(EcmaString::DATA_OFFSET), PtrMul(length, IntPtr(sizeof(uint16_t)))); + return PtrAdd(IntPtr(LineEcmaString::DATA_OFFSET), PtrMul(length, IntPtr(sizeof(uint16_t)))); } inline GateRef StubBuilder::AlignUp(GateRef x, GateRef alignment) @@ -2029,5 +2059,10 @@ inline void StubBuilder::SetRawHashcode(GateRef glue, GateRef str, GateRef rawHa { Store(VariableType::INT32(), glue, str, IntPtr(EcmaString::HASHCODE_OFFSET), rawHashcode); } + +inline GateRef StubBuilder::TryGetHashcodeFromString(GateRef string) +{ + return env_->GetBuilder()->TryGetHashcodeFromString(string); +} } // namespace panda::ecmascript::kungfu #endif // ECMASCRIPT_COMPILER_STUB_INL_H diff --git a/ecmascript/compiler/stub_builder.cpp b/ecmascript/compiler/stub_builder.cpp index 4b5c374732..ef020875f9 100644 --- a/ecmascript/compiler/stub_builder.cpp +++ b/ecmascript/compiler/stub_builder.cpp @@ -1081,7 +1081,7 @@ GateRef StubBuilder::IsDigit(GateRef ch) Int32GreaterThanOrEqual(ch, Int32('0'))); } -GateRef StubBuilder::StringToElementIndex(GateRef string) +GateRef StubBuilder::StringToElementIndex(GateRef glue, GateRef string) { auto env = GetEnvironment(); Label entry(env); @@ -1096,25 +1096,15 @@ GateRef StubBuilder::StringToElementIndex(GateRef string) Branch(Int32GreaterThan(len, Int32(MAX_ELEMENT_INDEX_LEN)), &exit, &inRange); Bind(&inRange); { - GateRef dataUtf16 = PtrAdd(string, IntPtr(EcmaString::DATA_OFFSET)); - DEFVARIABLE(c, VariableType::INT32(), Int32(0)); - Label isUtf16(env); Label isUtf8(env); - Label getChar1(env); GateRef isUtf16String = IsUtf16String(string); - Branch(isUtf16String, &isUtf16, &isUtf8); - Bind(&isUtf16); - { - c = ZExtInt16ToInt32(Load(VariableType::INT16(), dataUtf16)); - Jump(&getChar1); - } + Branch(isUtf16String, &exit, &isUtf8); Bind(&isUtf8); { - c = ZExtInt8ToInt32(Load(VariableType::INT8(), dataUtf16)); - Jump(&getChar1); - } - Bind(&getChar1); - { + GateRef strFlat = FlattenString(glue, string); + GateRef dataUtf8 = PtrAdd(strFlat, IntPtr(LineEcmaString::DATA_OFFSET)); + DEFVARIABLE(c, VariableType::INT32(), Int32(0)); + c = ZExtInt8ToInt32(Load(VariableType::INT8(), dataUtf8)); Label isDigitZero(env); Label notDigitZero(env); Branch(Int32Equal(*c, Int32('0')), &isDigitZero, ¬DigitZero); @@ -1141,38 +1131,19 @@ GateRef StubBuilder::StringToElementIndex(GateRef string) Branch(Int32UnsignedLessThan(*i, len), &loopHead, &afterLoop); LoopBegin(&loopHead); { - Label isUtf16A(env); - Label notUtf16(env); - Label getChar2(env); - Branch(isUtf16String, &isUtf16A, ¬Utf16); - Bind(&isUtf16A); + c = ZExtInt8ToInt32(Load(VariableType::INT8(), dataUtf8, ZExtInt32ToPtr(*i))); + Label isDigit2(env); + Label notDigit2(env); + Branch(IsDigit(*c), &isDigit2, ¬Digit2); + Bind(&isDigit2); { - // 2 : 2 means utf16 char width is two bytes - auto charOffset = PtrMul(ZExtInt32ToPtr(*i), IntPtr(2)); - c = ZExtInt16ToInt32(Load(VariableType::INT16(), dataUtf16, charOffset)); - Jump(&getChar2); - } - Bind(¬Utf16); - { - c = ZExtInt8ToInt32(Load(VariableType::INT8(), dataUtf16, ZExtInt32ToPtr(*i))); - Jump(&getChar2); - } - Bind(&getChar2); - { - Label isDigit2(env); - Label notDigit2(env); - Branch(IsDigit(*c), &isDigit2, ¬Digit2); - Bind(&isDigit2); - { - // 10 means the base of digit is 10. - n = Int32Add(Int32Mul(*n, Int32(10)), - Int32Sub(*c, Int32('0'))); - i = Int32Add(*i, Int32(1)); - Branch(Int32UnsignedLessThan(*i, len), &loopEnd, &afterLoop); - } - Bind(¬Digit2); - Jump(&exit); + // 10 means the base of digit is 10. + n = Int32Add(Int32Mul(*n, Int32(10)), Int32Sub(*c, Int32('0'))); + i = Int32Add(*i, Int32(1)); + Branch(Int32UnsignedLessThan(*i, len), &loopEnd, &afterLoop); } + Bind(¬Digit2); + Jump(&exit); } Bind(&loopEnd); LoopEnd(&loopHead); @@ -1196,7 +1167,7 @@ GateRef StubBuilder::StringToElementIndex(GateRef string) return ret; } -GateRef StubBuilder::TryToElementsIndex(GateRef key) +GateRef StubBuilder::TryToElementsIndex(GateRef glue, GateRef key) { auto env = GetEnvironment(); Label entry(env); @@ -1219,7 +1190,7 @@ GateRef StubBuilder::TryToElementsIndex(GateRef key) Branch(TaggedIsString(key), &isString, ¬String); Bind(&isString); { - resultKey = StringToElementIndex(key); + resultKey = StringToElementIndex(glue, key); Jump(&exit); } Bind(¬String); @@ -1437,7 +1408,7 @@ GateRef StubBuilder::LoadICWithHandler(GateRef glue, GateRef receiver, GateRef a return ret; } -GateRef StubBuilder::LoadElement(GateRef receiver, GateRef key) +GateRef StubBuilder::LoadElement(GateRef glue, GateRef receiver, GateRef key) { auto env = GetEnvironment(); Label entry(env); @@ -1448,7 +1419,7 @@ GateRef StubBuilder::LoadElement(GateRef receiver, GateRef key) Label lengthLessIndex(env); Label lengthNotLessIndex(env); DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); - GateRef index = TryToElementsIndex(key); + GateRef index = TryToElementsIndex(glue, key); Branch(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero); Bind(&indexLessZero); { @@ -1495,7 +1466,7 @@ GateRef StubBuilder::ICStoreElement(GateRef glue, GateRef receiver, GateRef key, Label loopEnd(env); DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); DEFVARIABLE(varHandler, VariableType::JS_ANY(), handler); - GateRef index = TryToElementsIndex(key); + GateRef index = TryToElementsIndex(glue, key); Branch(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero); Bind(&indexLessZero); { @@ -2030,7 +2001,7 @@ GateRef StubBuilder::GetPropertyByValue(GateRef glue, GateRef receiver, GateRef } Bind(&isNumberOrStringSymbol); { - GateRef index = TryToElementsIndex(*key); + GateRef index = TryToElementsIndex(glue, *key); Label validIndex(env); Label notValidIndex(env); Branch(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex); @@ -2736,7 +2707,7 @@ GateRef StubBuilder::SetPropertyByValue(GateRef glue, GateRef receiver, GateRef } Bind(&isNumberOrStringSymbol); { - GateRef index = TryToElementsIndex(*varKey); + GateRef index = TryToElementsIndex(glue, *varKey); Label validIndex(env); Label notValidIndex(env); Branch(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex); @@ -3473,12 +3444,22 @@ GateRef StubBuilder::FastStringEqual(GateRef glue, GateRef left, GateRef right) &exit); Bind(&hashcodeCompare); - Branch(Int32Equal(GetHashcodeFromString(glue, left), GetHashcodeFromString(glue, right)), &contentsCompare, - &exit); + Label leftNotNeg(env); + GateRef leftHash = TryGetHashcodeFromString(left); + GateRef rightHash = TryGetHashcodeFromString(right); + Branch(Int64Equal(leftHash, Int64(-1)), &contentsCompare, &leftNotNeg); + Bind(&leftNotNeg); + { + Label rightNotNeg(env); + Branch(Int64Equal(rightHash, Int64(-1)), &contentsCompare, &rightNotNeg); + Bind(&rightNotNeg); + Branch(Int64Equal(leftHash, rightHash), &contentsCompare, &exit); + } Bind(&contentsCompare); { - result = UpdateLeaveFrameAndCallNGCRuntime(glue, RTSTUB_ID(StringsAreEquals), { left, right }); + GateRef stringEqual = CallRuntime(glue, RTSTUB_ID(StringEqual), { left, right }); + result = Equal(stringEqual, TaggedTrue()); Jump(&exit); } @@ -4737,7 +4718,7 @@ void StubBuilder::CallFastPath(GateRef glue, GateRef nativeCode, GateRef func, G Bind(notFastBuiltins); } -GateRef StubBuilder::TryStringOrSymbelToElementIndex(GateRef key) +GateRef StubBuilder::TryStringOrSymbolToElementIndex(GateRef glue, GateRef key) { auto env = GetEnvironment(); Label entry(env); @@ -4760,8 +4741,8 @@ GateRef StubBuilder::TryStringOrSymbelToElementIndex(GateRef key) Label isUtf8(env); Branch(IsUtf16String(key), &exit, &isUtf8); Bind(&isUtf8); - - GateRef data = PtrAdd(key, IntPtr(EcmaString::DATA_OFFSET)); + GateRef keyFlat = FlattenString(glue, key); + GateRef data = PtrAdd(keyFlat, IntPtr(LineEcmaString::DATA_OFFSET)); DEFVARIABLE(c, VariableType::INT32(), Int32(0)); c = ZExtInt8ToInt32(Load(VariableType::INT8(), data)); Label isDigitZero(env); @@ -4871,7 +4852,7 @@ GateRef StubBuilder::GetTypeArrayPropertyByName(GateRef glue, GateRef receiver, } Bind(¬NegativeZero); { - GateRef index = TryStringOrSymbelToElementIndex(key); + GateRef index = TryStringOrSymbolToElementIndex(glue, key); Label validIndex(env); Label notValidIndex(env); Branch(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex); @@ -4932,7 +4913,7 @@ GateRef StubBuilder::SetTypeArrayPropertyByName(GateRef glue, GateRef receiver, } Bind(¬NegativeZero); { - GateRef index = TryStringOrSymbelToElementIndex(key); + GateRef index = TryStringOrSymbolToElementIndex(glue, key); Label validIndex(env); Label notValidIndex(env); Branch(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex); @@ -5006,4 +4987,40 @@ void StubBuilder::PGOProfiler(GateRef glue, GateRef func) env->SubCfgExit(); } } + +GateRef StubBuilder::FlattenString(GateRef glue, GateRef str) +{ + auto env = GetEnvironment(); + Label entry(env); + env->SubCfgEntry(&entry); + Label exit(env); + Label notLineString(env); + DEFVARIABLE(result, VariableType::JS_POINTER(), str); + Branch(IsLineString(str), &exit, ¬LineString); + Bind(¬LineString); + { + Label isTreeString(env); + Branch(IsTreeString(str), &isTreeString, &exit); + Bind(&isTreeString); + { + Label isFlat(env); + Label notFlat(env); + Branch(TreeStringIsFlat(str), &isFlat, ¬Flat); + Bind(&isFlat); + { + result = GetFirstFromTreeString(str); + Jump(&exit); + } + Bind(¬Flat); + { + result = CallRuntime(glue, RTSTUB_ID(SlowFlattenString), { str }); + Jump(&exit); + } + } + } + Bind(&exit); + auto ret = *result; + env->SubCfgExit(); + return ret; +} } // namespace panda::ecmascript::kungfu diff --git a/ecmascript/compiler/stub_builder.h b/ecmascript/compiler/stub_builder.h index 3de54b2858..b6a20f64c9 100644 --- a/ecmascript/compiler/stub_builder.h +++ b/ecmascript/compiler/stub_builder.h @@ -258,6 +258,9 @@ public: GateRef IsEcmaObject(GateRef obj); GateRef IsSymbol(GateRef obj); GateRef IsString(GateRef obj); + GateRef IsLineString(GateRef obj); + GateRef IsTreeString(GateRef obj); + GateRef TreeStringIsFlat(GateRef string); GateRef TaggedIsBigInt(GateRef obj); GateRef TaggedObjectIsBigInt(GateRef obj); GateRef IsJsProxy(GateRef obj); @@ -317,6 +320,9 @@ public: GateRef GetBitFieldFromHClass(GateRef hClass); GateRef GetLengthFromString(GateRef value); GateRef GetHashcodeFromString(GateRef glue, GateRef value); + GateRef TryGetHashcodeFromString(GateRef string); + GateRef GetFirstFromTreeString(GateRef string); + GateRef GetSecondFromTreeString(GateRef string); void SetBitFieldToHClass(GateRef glue, GateRef hClass, GateRef bitfield); void SetPrototypeToHClass(VariableType type, GateRef glue, GateRef hClass, GateRef proto); void SetProtoChangeDetailsToHClass(VariableType type, GateRef glue, GateRef hClass, @@ -370,15 +376,14 @@ public: GateRef IsUtf8String(GateRef string); GateRef IsInternalString(GateRef string); GateRef IsDigit(GateRef ch); - GateRef StringToElementIndex(GateRef string); - GateRef TryToElementsIndex(GateRef key); + GateRef StringToElementIndex(GateRef glue, GateRef string); GateRef ComputePropertyCapacityInJSObj(GateRef oldLength); GateRef FindTransitions(GateRef glue, GateRef receiver, GateRef hClass, GateRef key, GateRef attr); GateRef TaggedToRepresentation(GateRef value); GateRef LdGlobalRecord(GateRef glue, GateRef key); GateRef LoadFromField(GateRef receiver, GateRef handlerInfo); GateRef LoadGlobal(GateRef cell); - GateRef LoadElement(GateRef receiver, GateRef key); + GateRef LoadElement(GateRef glue, GateRef receiver, GateRef key); GateRef TryToElementsIndex(GateRef glue, GateRef key); GateRef CheckPolyHClass(GateRef cachedValue, GateRef hClass); GateRef LoadICWithHandler(GateRef glue, GateRef receiver, GateRef holder, GateRef handler); @@ -512,7 +517,7 @@ public: GateRef GetTypeArrayPropertyByName(GateRef glue, GateRef receiver, GateRef holder, GateRef key, GateRef jsType); GateRef SetTypeArrayPropertyByName(GateRef glue, GateRef receiver, GateRef holder, GateRef key, GateRef value, GateRef jsType); - GateRef TryStringOrSymbelToElementIndex(GateRef string); + GateRef TryStringOrSymbolToElementIndex(GateRef glue, GateRef string); inline GateRef DispatchBuiltins(GateRef glue, GateRef builtinsId, const std::initializer_list& args); GateRef ComputeSizeUtf8(GateRef length); GateRef ComputeSizeUtf16(GateRef length); @@ -524,6 +529,8 @@ public: inline void SetRawHashcode(GateRef glue, GateRef str, GateRef rawHashcode); void Assert(int messageId, int line, GateRef glue, GateRef condition, Label *nextLabel); void PGOProfiler(GateRef glue, GateRef func); + + GateRef FlattenString(GateRef glue, GateRef str); private: using BinaryOperation = std::function; template diff --git a/ecmascript/containers/tests/containers_treemap_test.cpp b/ecmascript/containers/tests/containers_treemap_test.cpp index 2ce10ed2bb..78174bb332 100644 --- a/ecmascript/containers/tests/containers_treemap_test.cpp +++ b/ecmascript/containers/tests/containers_treemap_test.cpp @@ -82,9 +82,9 @@ public: JSHandle valueY = GetCallArg(argv, 1); if (valueX->IsString() && valueY->IsString()) { - auto xString = static_cast(valueX->GetTaggedObject()); - auto yString = static_cast(valueY->GetTaggedObject()); - int result = EcmaStringAccessor::Compare(xString, yString); + auto xHandle = JSHandle(valueX); + auto yHandle = JSHandle(valueY); + int result = EcmaStringAccessor::Compare(thread->GetEcmaVM(), xHandle, yHandle); if (result < 0) { return JSTaggedValue(1); } diff --git a/ecmascript/containers/tests/containers_treeset_test.cpp b/ecmascript/containers/tests/containers_treeset_test.cpp index 53c1f691da..acd87f017f 100644 --- a/ecmascript/containers/tests/containers_treeset_test.cpp +++ b/ecmascript/containers/tests/containers_treeset_test.cpp @@ -79,9 +79,9 @@ public: JSHandle valueY = GetCallArg(argv, 1); if (valueX->IsString() && valueY->IsString()) { - auto xString = static_cast(valueX->GetTaggedObject()); - auto yString = static_cast(valueY->GetTaggedObject()); - int result = EcmaStringAccessor::Compare(xString, yString); + auto xHandle = JSHandle(valueX); + auto yHandle = JSHandle(valueY); + int result = EcmaStringAccessor::Compare(thread->GetEcmaVM(), xHandle, yHandle); if (result < 0) { return JSTaggedValue(1); } diff --git a/ecmascript/dfx/hprof/heap_snapshot.cpp b/ecmascript/dfx/hprof/heap_snapshot.cpp index a9c4e1bf32..9600fda290 100644 --- a/ecmascript/dfx/hprof/heap_snapshot.cpp +++ b/ecmascript/dfx/hprof/heap_snapshot.cpp @@ -217,7 +217,8 @@ CString *HeapSnapshot::GenerateNodeName(TaggedObject *entry) return GetArrayString(TaggedArray::Cast(entry), "COWArray["); case JSType::HCLASS: return GetString("HiddenClass"); - case JSType::STRING: + case JSType::LINE_STRING: + case JSType::TREE_STRING: return GetString("BaseString"); case JSType::JS_OBJECT: { CString objName = CString("JSOBJECT(Ctor="); // Ctor-name @@ -810,7 +811,7 @@ Node *HeapSnapshot::GenerateStringNode(JSTaggedValue entry, size_t size, int seq // Allocation Event will generate string node for "". // When we need to serialize and isFinish is true, the nodeName will be given the actual string content. auto originStr = static_cast(entry.GetTaggedObject()); - size_t selfsize = (size != 0) ? size : EcmaStringAccessor(originStr).ObjectSize(); + size_t selfsize = (size != 0) ? size : EcmaStringAccessor(originStr).GetFlatStringSize(); const CString *nodeName = &EMPTY_STRING; if (isInFinish) { nodeName = GetString(EntryVisitor::ConvertKey(entry)); @@ -833,7 +834,7 @@ Node *HeapSnapshot::GeneratePrivateStringNode(size_t size, int sequenceId) Node *node = nullptr; JSTaggedValue stringValue = vm_->GetJSThread()->GlobalConstants()->GetStringString(); auto originStr = static_cast(stringValue.GetTaggedObject()); - size_t selfsize = (size != 0) ? size : EcmaStringAccessor(originStr).ObjectSize(); + size_t selfsize = (size != 0) ? size : EcmaStringAccessor(originStr).GetFlatStringSize(); CString strContent; strContent.append(EntryVisitor::ConvertKey(stringValue)); node = Node::NewNode(vm_, sequenceId, nodeCount_, GetString(strContent), NodeType::PRIM_STRING, selfsize, diff --git a/ecmascript/dump.cpp b/ecmascript/dump.cpp index 816bd41da3..897ec10d28 100644 --- a/ecmascript/dump.cpp +++ b/ecmascript/dump.cpp @@ -142,7 +142,8 @@ CString JSHClass::DumpJSType(JSType type) return "ConstantPool"; case JSType::COW_TAGGED_ARRAY: return "COWArray"; - case JSType::STRING: + case JSType::LINE_STRING: + case JSType::TREE_STRING: return "BaseString"; case JSType::JS_NATIVE_POINTER: return "NativePointer"; @@ -575,7 +576,8 @@ static void DumpObject(TaggedObject *obj, std::ostream &os) case JSType::CONSTANT_POOL: DumpConstantPoolClass(ConstantPool::Cast(obj), os); break; - case JSType::STRING: + case JSType::LINE_STRING: + case JSType::TREE_STRING: DumpStringClass(EcmaString::Cast(obj), os); os << "\n"; break; @@ -1032,7 +1034,7 @@ void JSTaggedValue::DumpHeapObjectType(std::ostream &os) const } JSType type = obj->GetClass()->GetObjectType(); - if (type == JSType::STRING) { + if (type >= JSType::STRING_FIRST && type <= JSType::STRING_LAST) { CString string = ConvertToString(EcmaString::Cast(obj)); os << std::left << std::setw(DUMP_TYPE_OFFSET) << "[" + string + "]"; } else if (type == JSType::METHOD) { @@ -3459,7 +3461,8 @@ static void DumpObject(TaggedObject *obj, case JSType::CONSTANT_POOL: DumpConstantPoolClass(ConstantPool::Cast(obj), vec); return; - case JSType::STRING: + case JSType::LINE_STRING: + case JSType::TREE_STRING: DumpStringClass(EcmaString::Cast(obj), vec); return; case JSType::JS_NATIVE_POINTER: diff --git a/ecmascript/ecma_string-inl.h b/ecmascript/ecma_string-inl.h index 444060405f..7e607733cc 100644 --- a/ecmascript/ecma_string-inl.h +++ b/ecmascript/ecma_string-inl.h @@ -27,36 +27,12 @@ namespace panda::ecmascript { /* static */ inline EcmaString *EcmaString::CreateEmptyString(const EcmaVM *vm) { - auto string = vm->GetFactory()->AllocNonMovableStringObject(EcmaString::SIZE); + auto string = vm->GetFactory()->AllocNonMovableLineStringObject(EcmaString::SIZE); string->SetLength(0, true); string->SetRawHashcode(0); return string; } -/* static */ -inline EcmaString *EcmaString::AllocStringObjectWithSpaceType(const EcmaVM *vm, size_t length, bool compressed, - MemSpaceType type) -{ - size_t size = compressed ? ComputeSizeUtf8(length) : ComputeSizeUtf16(length); - EcmaString *string = nullptr; - switch (type) { - case MemSpaceType::SEMI_SPACE: - string = vm->GetFactory()->AllocStringObject(size); - break; - case MemSpaceType::OLD_SPACE: - string = vm->GetFactory()->AllocOldSpaceStringObject(size); - break; - case MemSpaceType::NON_MOVABLE: - string = vm->GetFactory()->AllocNonMovableStringObject(size); - break; - default: - UNREACHABLE(); - } - string->SetLength(length, compressed); - string->SetRawHashcode(0); - return string; -} - /* static */ inline EcmaString *EcmaString::CreateFromUtf8(const EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf8Len, bool canBeCompress, MemSpaceType type) @@ -66,7 +42,7 @@ inline EcmaString *EcmaString::CreateFromUtf8(const EcmaVM *vm, const uint8_t *u } EcmaString *string = nullptr; if (canBeCompress) { - string = AllocStringObjectWithSpaceType(vm, utf8Len, true, type); + string = CreateLineStringWithSpaceType(vm, utf8Len, true, type); ASSERT(string != nullptr); if (memcpy_s(string->GetDataUtf8Writable(), utf8Len, utf8Data, utf8Len) != EOK) { @@ -75,7 +51,7 @@ inline EcmaString *EcmaString::CreateFromUtf8(const EcmaVM *vm, const uint8_t *u } } else { auto utf16Len = base::utf_helper::Utf8ToUtf16Size(utf8Data, utf8Len); - string = AllocStringObjectWithSpaceType(vm, utf16Len, false, type); + string = CreateLineStringWithSpaceType(vm, utf16Len, false, type); ASSERT(string != nullptr); [[maybe_unused]] auto len = @@ -93,11 +69,11 @@ inline EcmaString *EcmaString::CreateFromUtf16(const EcmaVM *vm, const uint16_t if (utf16Len == 0) { return vm->GetFactory()->GetEmptyString().GetObject(); } - auto string = AllocStringObjectWithSpaceType(vm, utf16Len, canBeCompress, type); + auto string = CreateLineStringWithSpaceType(vm, utf16Len, canBeCompress, type); ASSERT(string != nullptr); if (canBeCompress) { - CopyUtf16AsUtf8(utf16Data, string->GetDataUtf8Writable(), utf16Len); + CopyChars(string->GetDataUtf8Writable(), utf16Data, utf16Len); } else { uint32_t len = utf16Len * (sizeof(uint16_t) / sizeof(uint8_t)); if (memcpy_s(string->GetDataUtf16Writable(), len, utf16Data, len) != EOK) { @@ -110,8 +86,244 @@ inline EcmaString *EcmaString::CreateFromUtf16(const EcmaVM *vm, const uint16_t return string; } +/* static */ +inline EcmaString *EcmaString::CreateLineString(const EcmaVM *vm, size_t length, bool compressed) +{ + size_t size = compressed ? LineEcmaString::ComputeSizeUtf8(length) : LineEcmaString::ComputeSizeUtf16(length); + auto string = vm->GetFactory()->AllocLineStringObject(size); + string->SetLength(length, compressed); + string->SetRawHashcode(0); + return string; +} + +/* static */ +inline EcmaString *EcmaString::CreateLineStringNoGC(const EcmaVM *vm, size_t length, bool compressed) +{ + size_t size = compressed ? LineEcmaString::ComputeSizeUtf8(length) : LineEcmaString::ComputeSizeUtf16(length); + size = AlignUp(size, static_cast(MemAlignment::MEM_ALIGN_OBJECT)); + auto object = reinterpret_cast(vm->GetHeap()->GetOldSpace()->Allocate(size)); + object->SetClass(JSHClass::Cast(vm->GetJSThread()->GlobalConstants()->GetLineStringClass().GetTaggedObject())); + auto string = EcmaString::Cast(object); + string->SetLength(length, compressed); + string->SetRawHashcode(0); + return string; +} + +/* static */ +inline EcmaString *EcmaString::CreateLineStringWithSpaceType(const EcmaVM *vm, size_t length, bool compressed, + MemSpaceType type) +{ + size_t size = compressed ? LineEcmaString::ComputeSizeUtf8(length) : LineEcmaString::ComputeSizeUtf16(length); + EcmaString *string = nullptr; + switch (type) { + case MemSpaceType::SEMI_SPACE: + string = vm->GetFactory()->AllocLineStringObject(size); + break; + case MemSpaceType::OLD_SPACE: + string = vm->GetFactory()->AllocOldSpaceLineStringObject(size); + break; + case MemSpaceType::NON_MOVABLE: + string = vm->GetFactory()->AllocNonMovableLineStringObject(size); + break; + default: + UNREACHABLE(); + } + string->SetLength(length, compressed); + string->SetRawHashcode(0); + return string; +} + +inline EcmaString *EcmaString::CreateTreeString(const EcmaVM *vm, + const JSHandle &left, const JSHandle &right, uint32_t length, bool compressed) +{ + auto thread = vm->GetJSThread(); + auto string = TreeEcmaString::Cast(vm->GetFactory()->AllocTreeStringObject()); + string->SetLength(length, compressed); + string->SetRawHashcode(0); + string->SetFirst(thread, left.GetTaggedValue()); + string->SetSecond(thread, right.GetTaggedValue()); + return string; +} + +/* static */ +EcmaString *EcmaString::FastSubUtf8String(const EcmaVM *vm, const JSHandle &src, uint32_t start, + uint32_t length) +{ + ASSERT(src->IsLineString()); + auto string = CreateLineString(vm, length, true); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + Span dst(string->GetDataUtf8Writable(), length); + Span source(src->GetDataUtf8() + start, length); + EcmaString::MemCopyChars(dst, length, source, length); + + 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 length) +{ + ASSERT(src->IsLineString()); + bool canBeCompressed = CanBeCompressed(src->GetDataUtf16() + start, length); + auto string = CreateLineString(vm, length, canBeCompressed); + if (canBeCompressed) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + CopyChars(string->GetDataUtf8Writable(), src->GetDataUtf16() + start, length); + } else { + uint32_t len = length * (sizeof(uint16_t) / sizeof(uint8_t)); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + Span dst(string->GetDataUtf16Writable(), length); + Span source(src->GetDataUtf16() + start, length); + EcmaString::MemCopyChars(dst, len, source, len); + } + ASSERT_PRINT(canBeCompressed == CanBeCompressed(string), "canBeCompresse does not match the real value!"); + return string; +} + +inline uint16_t *EcmaString::GetData() const +{ + ASSERT_PRINT(IsLineString(), "EcmaString: Read data from not LineString"); + return LineEcmaString::Cast(this)->GetData(); +} + +inline const uint8_t *EcmaString::GetDataUtf8() const +{ + ASSERT_PRINT(IsUtf8(), "EcmaString: Read data as utf8 for utf16 string"); + return reinterpret_cast(GetData()); +} + +inline const uint16_t *EcmaString::GetDataUtf16() const +{ + LOG_ECMA_IF(!IsUtf16(), FATAL) << "EcmaString: Read data as utf16 for utf8 string"; + return GetData(); +} + +inline uint8_t *EcmaString::GetDataUtf8Writable() +{ + ASSERT_PRINT(IsUtf8(), "EcmaString: Read data as utf8 for utf16 string"); + return reinterpret_cast(GetData()); +} + +inline uint16_t *EcmaString::GetDataUtf16Writable() +{ + LOG_ECMA_IF(!IsUtf16(), FATAL) << "EcmaString: Read data as utf16 for utf8 string"; + return GetData(); +} + +inline size_t EcmaString::GetUtf8Length(bool modify) const +{ + ASSERT(IsLineString()); + if (!IsUtf16()) { + return GetLength() + 1; // add place for zero in the end + } + return base::utf_helper::Utf16ToUtf8Size(GetData(), GetLength(), modify); +} + template inline uint16_t EcmaString::At(int32_t index) const +{ + int32_t length = static_cast(GetLength()); + if (verify) { + if ((index < 0) || (index >= length)) { + return 0; + } + } + if (IsLineString()) { + return LineEcmaString::Cast(this)->Get(index); + } else { + return TreeEcmaString::Cast(this)->Get(index); + } +} + +inline void EcmaString::WriteData(uint32_t index, uint16_t src) +{ + ASSERT(index < GetLength()); + ASSERT(IsLineString()); + LineEcmaString::Cast(this)->Set(index, src); +} + +inline bool EcmaString::IsFlat() const +{ + if (!JSTaggedValue(this).IsTreeString()) { + return true; + } + return TreeEcmaString::Cast(this)->IsFlat(); +} + +template +void EcmaString::WriteToFlat(EcmaString *src, Char *buf, uint32_t maxLength) +{ + DISALLOW_GARBAGE_COLLECTION; + uint32_t length = src->GetLength(); + if (length == 0) { + return; + } + while (true) { + ASSERT(length <= maxLength && length > 0); + ASSERT(length <= src->GetLength()); + switch (src->GetStringType()) { + case JSType::LINE_STRING: { + if (src->IsUtf8()) { + CopyChars(buf, src->GetDataUtf8(), length); + } else { + CopyChars(buf, src->GetDataUtf16(), length); + } + return; + } + case JSType::TREE_STRING: { + TreeEcmaString *treeSrc = TreeEcmaString::Cast(src); + EcmaString *first = EcmaString::Cast(treeSrc->GetFirst()); + EcmaString *second = EcmaString::Cast(treeSrc->GetSecond()); + uint32_t firstLength = first->GetLength(); + uint32_t secondLength = second->GetLength(); + if (secondLength >= firstLength) { + // second string is longer. So recurse over first. + WriteToFlat(first, buf, maxLength); + if (first == second) { + CopyChars(buf + firstLength, buf, firstLength); + return; + } + buf += firstLength; + maxLength -= firstLength; + src = second; + length -= firstLength; + } else { + // first string is longer. So recurse over second. + if (secondLength > 0) { + if (secondLength == 1) { + buf[firstLength] = static_cast(second->At(0)); + } else if (second->IsLineString() && second->IsUtf8()) { + CopyChars(buf + firstLength, second->GetDataUtf8(), secondLength); + } else { + WriteToFlat(second, buf + firstLength, maxLength - firstLength); + } + } + maxLength = firstLength; + src = first; + length -= secondLength; + } + continue; + } + default: + UNREACHABLE(); + } + } +} + +/* static */ +template +void EcmaString::CopyChars(DstType *dst, SrcType *src, uint32_t count) +{ + Span srcSp(src, count); + Span dstSp(dst, count); + for (uint32_t i = 0; i < count; i++) { + dstSp[i] = srcSp[i]; + } +} + +template +uint16_t LineEcmaString::Get(int32_t index) const { int32_t length = static_cast(GetLength()); if (verify) { @@ -127,54 +339,56 @@ inline uint16_t EcmaString::At(int32_t index) const return sp[index]; } -/* static */ -inline EcmaString *EcmaString::AllocStringObject(const EcmaVM *vm, size_t length, bool compressed) +template +uint16_t TreeEcmaString::Get(int32_t index) const { - size_t size = compressed ? ComputeSizeUtf8(length) : ComputeSizeUtf16(length); - auto string = reinterpret_cast(vm->GetFactory()->AllocStringObject(size)); - string->SetLength(length, compressed); - string->SetRawHashcode(0); - return string; + int32_t length = static_cast(GetLength()); + if (verify) { + if ((index < 0) || (index >= length)) { + return 0; + } + } + + if (IsFlat()) { + EcmaString *first = EcmaString::Cast(GetFirst()); + return first->At(index); + } + EcmaString *string = const_cast(this); + while (true) { + if (string->IsTreeString()) { + EcmaString *first = EcmaString::Cast(TreeEcmaString::Cast(string)->GetFirst()); + if (static_cast(first->GetLength()) > index) { + string = first; + } else { + index -= static_cast(first->GetLength()); + string = EcmaString::Cast(TreeEcmaString::Cast(string)->GetSecond()); + } + } else { + return string->At(index); + } + } + UNREACHABLE(); } -/* static */ -EcmaString *EcmaString::FastSubUtf8String(const EcmaVM *vm, const JSHandle &src, uint32_t start, - uint32_t length) +inline const uint8_t *EcmaStringAccessor::GetDataUtf8() { - if (length == 0) { - return *vm->GetFactory()->GetEmptyString(); - } - auto string = AllocStringObject(vm, length, true); - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - 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; + return string_->GetDataUtf8(); } -/* static */ -EcmaString *EcmaString::FastSubUtf16String(const EcmaVM *vm, const JSHandle &src, uint32_t start, - uint32_t length) +inline const uint16_t *EcmaStringAccessor::GetDataUtf16() { - if (length == 0) { - return *vm->GetFactory()->GetEmptyString(); - } - bool canBeCompressed = CanBeCompressed(src->GetDataUtf16() + start, length); - auto string = AllocStringObject(vm, length, canBeCompressed); - if (canBeCompressed) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - CopyUtf16AsUtf8(src->GetDataUtf16() + start, string->GetDataUtf8Writable(), length); - } else { - uint32_t len = length * (sizeof(uint16_t) / sizeof(uint8_t)); - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - 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!"); - return string; + return string_->GetDataUtf16(); +} + +inline size_t EcmaStringAccessor::GetUtf8Length() const +{ + return string_->GetUtf8Length(); +} + +inline void EcmaStringAccessor::ReadData(EcmaString * dst, EcmaString *src, + uint32_t start, uint32_t destSize, uint32_t length) +{ + dst->WriteData(src, start, destSize, length); } } // namespace panda::ecmascript #endif diff --git a/ecmascript/ecma_string.cpp b/ecmascript/ecma_string.cpp index 81d34c01ca..46f49f679a 100644 --- a/ecmascript/ecma_string.cpp +++ b/ecmascript/ecma_string.cpp @@ -22,71 +22,117 @@ namespace panda::ecmascript { static constexpr int SMALL_STRING_SIZE = 128; EcmaString *EcmaString::Concat(const EcmaVM *vm, - const JSHandle &str1Handle, const JSHandle &str2Handle) + const JSHandle &left, const JSHandle &right) { // allocator may trig gc and move src, need to hold it - EcmaString *string1 = *str1Handle; - EcmaString *string2 = *str2Handle; + EcmaString *strLeft = *left; + EcmaString *strRight = *right; + uint32_t leftLength = strLeft->GetLength(); + if (leftLength == 0) { + return strRight; + } + uint32_t rightLength = strRight->GetLength(); + if (rightLength == 0) { + return strLeft; + } - uint32_t length1 = string1->GetLength(); - - uint32_t length2 = string2->GetLength(); - uint32_t newLength = length1 + length2; + uint32_t newLength = leftLength + rightLength; if (newLength == 0) { return vm->GetFactory()->GetEmptyString().GetObject(); - } else if (length1 == 0) { - return string2; - } else if (length2 == 0) { - return string1; - } - bool compressed = (!string1->IsUtf16() && !string2->IsUtf16()); - auto newString = AllocStringObject(vm, newLength, compressed); - - // retrieve strings after gc - string1 = *str1Handle; - string2 = *str2Handle; - if (compressed) { - Span sp(newString->GetDataUtf8Writable(), newLength); - Span src1(string1->GetDataUtf8(), length1); - EcmaString::StringCopy(sp, newLength, src1, length1); - - sp = sp.SubSpan(length1); - Span src2(string2->GetDataUtf8(), length2); - EcmaString::StringCopy(sp, newLength - length1, src2, length2); - } else { - Span sp(newString->GetDataUtf16Writable(), newLength); - if (!string1->IsUtf16()) { - for (uint32_t i = 0; i < length1; ++i) { - sp[i] = string1->At(i); - } - } else { - Span src1(string1->GetDataUtf16(), length1); - EcmaString::StringCopy(sp, newLength << 1U, src1, length1 << 1U); - } - sp = sp.SubSpan(length1); - if (!string2->IsUtf16()) { - for (uint32_t i = 0; i < length2; ++i) { - sp[i] = string2->At(i); - } - } else { - uint32_t length = length2 << 1U; - Span src2(string2->GetDataUtf16(), length2); - EcmaString::StringCopy(sp, length, src2, length); - } } - ASSERT_PRINT(compressed == CanBeCompressed(newString), "compressed does not match the real value!"); - return newString; + bool compressed = (strLeft->IsUtf8() && strRight->IsUtf8()); + + // if the result string is small, make a LineString + if (newLength < TreeEcmaString::MIN_TREE_ECMASTRING_LENGTH) { + ASSERT(strLeft->IsLineString()); + ASSERT(strRight->IsLineString()); + auto newString = CreateLineString(vm, newLength, compressed); + // retrieve strings after gc + strLeft = *left; + strRight = *right; + if (compressed) { + // copy left part + Span sp(newString->GetDataUtf8Writable(), newLength); + Span srcLeft(strLeft->GetDataUtf8(), leftLength); + EcmaString::MemCopyChars(sp, newLength, srcLeft, leftLength); + // copy right part + sp = sp.SubSpan(leftLength); + Span srcRight(strRight->GetDataUtf8(), rightLength); + EcmaString::MemCopyChars(sp, rightLength, srcRight, rightLength); + } else { + // copy left part + Span sp(newString->GetDataUtf16Writable(), newLength); + if (strLeft->IsUtf8()) { + EcmaString::CopyChars(sp.data(), strLeft->GetDataUtf8(), leftLength); + } else { + Span srcLeft(strLeft->GetDataUtf16(), leftLength); + EcmaString::MemCopyChars(sp, newLength << 1U, srcLeft, leftLength << 1U); + } + // copy right part + sp = sp.SubSpan(leftLength); + if (strRight->IsUtf8()) { + EcmaString::CopyChars(sp.data(), strRight->GetDataUtf8(), rightLength); + } else { + Span srcRight(strRight->GetDataUtf16(), rightLength); + EcmaString::MemCopyChars(sp, rightLength << 1U, srcRight, rightLength << 1U); + } + } + ASSERT_PRINT(compressed == CanBeCompressed(newString), "compressed does not match the real value!"); + return newString; + } + return CreateTreeString(vm, left, right, newLength, compressed); } /* static */ EcmaString *EcmaString::FastSubString(const EcmaVM *vm, - const JSHandle &src, uint32_t start, uint32_t utf16Len) + const JSHandle &src, uint32_t start, uint32_t length) { - if (src->IsUtf8()) { - return FastSubUtf8String(vm, src, start, utf16Len); + ASSERT((start + length) <= src->GetLength()); + if (length == 0) { + return *vm->GetFactory()->GetEmptyString(); + } + if (start == 0 && length == src->GetLength()) { + return *src; + } + auto srcFlat = JSHandle(vm->GetJSThread(), Flatten(vm, src)); + if (srcFlat->IsUtf8()) { + return FastSubUtf8String(vm, srcFlat, start, length); + } + return FastSubUtf16String(vm, srcFlat, start, length); +} + +void EcmaString::WriteData(EcmaString *src, uint32_t start, uint32_t destSize, uint32_t length) +{ + ASSERT(IsLineString()); + if (IsUtf8()) { + ASSERT(src->IsUtf8()); + CVector buf; + const uint8_t *data = EcmaString::GetUtf8DataFlat(src, buf); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + if (length != 0 && memcpy_s(GetDataUtf8Writable() + start, destSize, data, length) != EOK) { + LOG_FULL(FATAL) << "memcpy_s failed"; + UNREACHABLE(); + } + } else if (src->IsUtf8()) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + CVector buf; + const uint8_t *data = EcmaString::GetUtf8DataFlat(src, buf); + Span to(GetDataUtf16Writable() + start, length); + Span from(data, length); + for (uint32_t i = 0; i < length; i++) { + to[i] = from[i]; + } + } else { + CVector buf; + const uint16_t *data = EcmaString::GetUtf16DataFlat(src, buf); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + if (length != 0 && memcpy_s(GetDataUtf16Writable() + start, + destSize * sizeof(uint16_t), data, length * sizeof(uint16_t)) != EOK) { + LOG_FULL(FATAL) << "memcpy_s failed"; + UNREACHABLE(); + } } - return FastSubUtf16String(vm, src, start, utf16Len); } template @@ -102,11 +148,15 @@ int32_t CompareStringSpan(Span &lhsSp, Span &rhsSp, int32_t count) return 0; } -int32_t EcmaString::Compare(EcmaString *lhs, EcmaString *rhs) +int32_t EcmaString::Compare(const EcmaVM *vm, const JSHandle &left, const JSHandle &right) { - if (lhs == rhs) { + if (*left == *right) { return 0; } + auto leftFlat = JSHandle(vm->GetJSThread(), Flatten(vm, left)); + auto rightFlat = JSHandle(vm->GetJSThread(), Flatten(vm, right)); + EcmaString *lhs = *leftFlat; + EcmaString *rhs = *rightFlat; int32_t lhsCount = static_cast(lhs->GetLength()); int32_t rhsCount = static_cast(rhs->GetLength()); int32_t countDiff = lhsCount - rhsCount; @@ -198,8 +248,11 @@ int32_t EcmaString::LastIndexOf(Span &lhsSp, Span &rhsSp, in return -1; } -int32_t EcmaString::IndexOf(EcmaString *lhs, EcmaString *rhs, int pos) +int32_t EcmaString::IndexOf(const EcmaVM *vm, + const JSHandle &receiver, const JSHandle &search, int pos) { + EcmaString *lhs = *receiver; + EcmaString *rhs = *search; if (lhs == nullptr || rhs == nullptr) { return -1; } @@ -222,6 +275,16 @@ int32_t EcmaString::IndexOf(EcmaString *lhs, EcmaString *rhs, int pos) if (max < 0) { return -1; } + + if (pos + rhsCount > lhsCount) { + return -1; + } + + auto receiverFlat = JSHandle(vm->GetJSThread(), Flatten(vm, receiver)); + auto searchFlat = JSHandle(vm->GetJSThread(), Flatten(vm, search)); + lhs = *receiverFlat; + rhs = *searchFlat; + if (rhs->IsUtf8() && lhs->IsUtf8()) { Span lhsSp(lhs->GetDataUtf8(), lhsCount); Span rhsSp(rhs->GetDataUtf8(), rhsCount); @@ -239,8 +302,11 @@ int32_t EcmaString::IndexOf(EcmaString *lhs, EcmaString *rhs, int pos) } } -int32_t EcmaString::LastIndexOf(EcmaString *lhs, EcmaString *rhs, int pos) +int32_t EcmaString::LastIndexOf(const EcmaVM *vm, + const JSHandle &receiver, const JSHandle &search, int pos) { + EcmaString *lhs = *receiver; + EcmaString *rhs = *search; if (lhs == nullptr || rhs == nullptr) { return -1; } @@ -267,6 +333,11 @@ int32_t EcmaString::LastIndexOf(EcmaString *lhs, EcmaString *rhs, int pos) return pos; } + auto receiverFlat = JSHandle(vm->GetJSThread(), Flatten(vm, receiver)); + auto searchFlat = JSHandle(vm->GetJSThread(), Flatten(vm, search)); + lhs = *receiverFlat; + rhs = *searchFlat; + if (rhs->IsUtf8() && lhs->IsUtf8()) { Span lhsSp(lhs->GetDataUtf8(), lhsCount); Span rhsSp(rhs->GetDataUtf8(), rhsCount); @@ -289,9 +360,13 @@ std::u16string EcmaString::ToU16String(uint32_t len) uint32_t length = len > 0 ? len : GetLength(); std::u16string result; if (IsUtf16()) { - result = base::StringHelper::Utf16ToU16String(GetDataUtf16(), length); + CVector buf; + const uint16_t *data = EcmaString::GetUtf16DataFlat(this, buf); + result = base::StringHelper::Utf16ToU16String(data, length); } else { - result = base::StringHelper::Utf8ToU16String(GetDataUtf8(), length); + CVector buf; + const uint8_t *data = EcmaString::GetUtf8DataFlat(this, buf); + result = base::StringHelper::Utf8ToU16String(data, length); } return result; } @@ -299,6 +374,7 @@ std::u16string EcmaString::ToU16String(uint32_t len) // static bool EcmaString::CanBeCompressed(const EcmaString *string) { + ASSERT(string->IsLineString()); if (string->IsUtf8()) { return CanBeCompressed(string->GetDataUtf8(), string->GetLength()); } @@ -336,18 +412,10 @@ bool EcmaString::CanBeCompressed(const uint16_t *utf16Data, uint32_t utf16Len) return isCompressed; } -/* static */ -void EcmaString::CopyUtf16AsUtf8(const uint16_t *utf16From, uint8_t *utf8To, uint32_t utf16Len) -{ - Span from(utf16From, utf16Len); - Span to(utf8To, utf16Len); - for (uint32_t i = 0; i < utf16Len; i++) { - to[i] = from[i]; - } -} - bool EcmaString::EqualToSplicedString(const EcmaString *str1, const EcmaString *str2) { + ASSERT(IsLineString()); + ASSERT(str1->IsLineString() && str2->IsLineString()); if (GetLength() != str1->GetLength() + str2->GetLength()) { return false; } @@ -377,23 +445,77 @@ bool EcmaString::EqualToSplicedString(const EcmaString *str1, const EcmaString * bool EcmaString::StringsAreEqualSameUtfEncoding(EcmaString *str1, EcmaString *str2) { if (str1->IsUtf16()) { - Span data1(str1->GetDataUtf16(), str1->GetLength()); - Span data2(str2->GetDataUtf16(), str1->GetLength()); - return EcmaString::StringsAreEquals(data1, data2); + CVector buf1; + CVector buf2; + const uint16_t *data1 = EcmaString::GetUtf16DataFlat(str1, buf1); + const uint16_t *data2 = EcmaString::GetUtf16DataFlat(str2, buf2); + Span sp1(data1, str1->GetLength()); + Span sp2(data2, str2->GetLength()); + return EcmaString::StringsAreEquals(sp1, sp2); } else { // NOLINT(readability-else-after-return) - Span data1(str1->GetDataUtf8(), str1->GetLength()); - Span data2(str2->GetDataUtf8(), str1->GetLength()); - return EcmaString::StringsAreEquals(data1, data2); + CVector buf1; + CVector buf2; + const uint8_t *data1 = EcmaString::GetUtf8DataFlat(str1, buf1); + const uint8_t *data2 = EcmaString::GetUtf8DataFlat(str2, buf2); + Span sp1(data1, str1->GetLength()); + Span sp2(data2, str2->GetLength()); + return EcmaString::StringsAreEquals(sp1, sp2); } } +bool EcmaString::StringsAreEqual(const EcmaVM *vm, const JSHandle &str1, const JSHandle &str2) +{ + if (str1 == str2) { + return true; + } + if (str1->IsUtf16() != str2->IsUtf16()) { + return false; + } + uint32_t str1Len = str1->GetLength(); + if (str1Len != str2->GetLength()) { + return false; + } + if (str1Len == 0) { + return true; + } + + uint32_t str1Hash; + uint32_t str2Hash; + if (str1->TryGetHashCode(&str1Hash) && str2->TryGetHashCode(&str2Hash)) { + if (str1Hash != str2Hash) { + return false; + } + } + + auto str1Flat = JSHandle(vm->GetJSThread(), Flatten(vm, str1)); + auto str2Flat = JSHandle(vm->GetJSThread(), Flatten(vm, str2)); + return StringsAreEqualSameUtfEncoding(*str1Flat, *str2Flat); +} + /* static */ bool EcmaString::StringsAreEqual(EcmaString *str1, EcmaString *str2) { - if ((str1->IsUtf16() != str2->IsUtf16()) || (str1->GetLength() != str2->GetLength()) || - (str1->GetHashcode() != str2->GetHashcode())) { + if (str1 == str2) { + return true; + } + if (str1->IsUtf16() != str2->IsUtf16()) { return false; } + uint32_t str1Len = str1->GetLength(); + if (str1Len != str2->GetLength()) { + return false; + } + if (str1Len == 0) { + return true; + } + + uint32_t str1Hash; + uint32_t str2Hash; + if (str1->TryGetHashCode(&str1Hash) && str2->TryGetHashCode(&str2Hash)) { + if (str1Hash != str2Hash) { + return false; + } + } return StringsAreEqualSameUtfEncoding(str1, str2); } @@ -404,33 +526,38 @@ bool EcmaString::StringsAreEqualUtf8(const EcmaString *str1, const uint8_t *utf8 if (canBeCompress != str1->IsUtf8()) { return false; } - if (canBeCompress && str1->GetLength() != utf8Len) { return false; } - if (canBeCompress) { - Span data1(str1->GetDataUtf8(), utf8Len); + CVector buf; + Span data1(EcmaString::GetUtf8DataFlat(str1, buf), utf8Len); Span data2(utf8Data, utf8Len); return EcmaString::StringsAreEquals(data1, data2); } - return IsUtf8EqualsUtf16(utf8Data, utf8Len, str1->GetDataUtf16(), str1->GetLength()); + CVector buf; + uint32_t length = str1->GetLength(); + const uint16_t *data = EcmaString::GetUtf16DataFlat(str1, buf); + return IsUtf8EqualsUtf16(utf8Data, utf8Len, data, length); } /* static */ bool EcmaString::StringsAreEqualUtf16(const EcmaString *str1, const uint16_t *utf16Data, uint32_t utf16Len) { - bool result = false; - if (str1->GetLength() != utf16Len) { - result = false; - } else if (!str1->IsUtf16()) { - result = IsUtf8EqualsUtf16(str1->GetDataUtf8(), str1->GetLength(), utf16Data, utf16Len); - } else { - Span data1(str1->GetDataUtf16(), str1->GetLength()); - Span data2(utf16Data, utf16Len); - result = EcmaString::StringsAreEquals(data1, data2); + uint32_t length = str1->GetLength(); + if (length != utf16Len) { + return false; + } + if (str1->IsUtf8()) { + CVector buf; + const uint8_t *data = EcmaString::GetUtf8DataFlat(str1, buf); + return IsUtf8EqualsUtf16(data, length, utf16Data, utf16Len); + } else { + CVector buf; + Span data1(EcmaString::GetUtf16DataFlat(str1, buf), length); + Span data2(utf16Data, utf16Len); + return EcmaString::StringsAreEquals(data1, data2); } - return result; } /* static */ @@ -451,7 +578,7 @@ bool EcmaString::StringsAreEquals(Span &str1, Span &str2) } template -bool EcmaString::StringCopy(Span &dst, size_t dstMax, Span &src, size_t count) +bool EcmaString::MemCopyChars(Span &dst, size_t dstMax, Span &src, size_t count) { ASSERT(dstMax >= count); ASSERT(dst.Size() >= src.Size()); @@ -463,7 +590,7 @@ bool EcmaString::StringCopy(Span &dst, size_t dstMax, Span &src, siz } template -static int32_t ComputeHashForData(const T *data, size_t size, uint32_t hashSeed) +static uint32_t ComputeHashForData(const T *data, size_t size, uint32_t hashSeed) { uint32_t hash = hashSeed; Span sp(data, size); @@ -471,40 +598,31 @@ static int32_t ComputeHashForData(const T *data, size_t size, uint32_t hashSeed) constexpr size_t SHIFT = 5; hash = (hash << SHIFT) - hash + c; } - return static_cast(hash); -} - -static int32_t ComputeHashForUtf8(const uint8_t *utf8Data, uint32_t utf8DataLength) -{ - if (utf8Data == nullptr) { - return 0; - } - uint32_t hash = 0; - const uint8_t *end = utf8Data + utf8DataLength; - while (utf8Data < end) { // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) - constexpr size_t SHIFT = 5; - hash = (hash << SHIFT) - hash + *utf8Data++; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) - } - return static_cast(hash); + return hash; } uint32_t EcmaString::ComputeHashcode(uint32_t hashSeed) const { - int32_t hash; - if (!IsUtf16()) { - hash = ComputeHashForData(GetDataUtf8(), GetLength(), hashSeed); + uint32_t hash; + uint32_t length = GetLength(); + if (IsUtf8()) { + CVector buf; + const uint8_t *data = EcmaString::GetUtf8DataFlat(this, buf); + hash = ComputeHashForData(data, length, hashSeed); } else { - hash = ComputeHashForData(GetDataUtf16(), GetLength(), hashSeed); + CVector buf; + const uint16_t *data = EcmaString::GetUtf16DataFlat(this, buf); + hash = ComputeHashForData(data, length, hashSeed); } - return static_cast(hash); + return hash; } /* static */ uint32_t EcmaString::ComputeHashcodeUtf8(const uint8_t *utf8Data, size_t utf8Len, bool canBeCompress) { - int32_t hash; + uint32_t hash; if (canBeCompress) { - hash = ComputeHashForUtf8(utf8Data, utf8Len); + hash = ComputeHashForData(utf8Data, utf8Len, 0); } else { auto utf16Len = base::utf_helper::Utf8ToUtf16Size(utf8Data, utf8Len); CVector tmpBuffer(utf16Len); @@ -513,7 +631,7 @@ uint32_t EcmaString::ComputeHashcodeUtf8(const uint8_t *utf8Data, size_t utf8Len ASSERT(len == utf16Len); hash = ComputeHashForData(tmpBuffer.data(), utf16Len, 0); } - return static_cast(hash); + return hash; } /* static */ @@ -549,7 +667,9 @@ bool EcmaString::ToElementIndex(uint32_t *index) return false; } - uint32_t c = GetDataUtf8()[0]; + CVector buf; + const uint8_t *data = EcmaString::GetUtf8DataFlat(this, buf); + uint32_t c = data[0]; uint64_t n = 0; if (c == '0') { *index = 0; @@ -558,7 +678,7 @@ bool EcmaString::ToElementIndex(uint32_t *index) if (c > '0' && c <= '9') { n = c - '0'; for (uint32_t i = 1; i < len; i++) { - c = GetDataUtf8()[i]; // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + c = data[i]; // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) if (c < '0' || c > '9') { return false; } @@ -583,7 +703,9 @@ bool EcmaString::ToTypedArrayIndex(uint32_t *index) return false; } - uint32_t c = GetDataUtf8()[0]; // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + CVector buf; + const uint8_t *data = EcmaString::GetUtf8DataFlat(this, buf); + uint32_t c = data[0]; // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) uint64_t n = 0; if (c == '0') { *index = 0; @@ -592,7 +714,7 @@ bool EcmaString::ToTypedArrayIndex(uint32_t *index) if (c > '0' && c <= '9') { n = c - '0'; for (uint32_t i = 1; i < len; i++) { - c = GetDataUtf8()[i]; // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + c = data[i]; // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) if (c >= '0' && c <= '9') { // NOLINTNEXTLINE(readability-magic-numbers) n = n * 10 + (c - '0'); // 10: decimal factor @@ -637,17 +759,18 @@ EcmaString *EcmaString::TrimBody(const JSThread *thread, const JSHandle &src) { - uint32_t srcLength = src->GetLength(); + auto srcFlat = JSHandle(vm->GetJSThread(), Flatten(vm, src)); + uint32_t srcLength = srcFlat->GetLength(); auto factory = vm->GetFactory(); - if (src->IsUtf16()) { - std::u16string u16str = base::StringHelper::Utf16ToU16String(src->GetDataUtf16(), srcLength); + if (srcFlat->IsUtf16()) { + std::u16string u16str = base::StringHelper::Utf16ToU16String(srcFlat->GetDataUtf16(), srcLength); std::string res = base::StringHelper::ToLower(u16str); return *(factory->NewFromStdString(res)); } else { const char start = 'A'; const char end = 'Z'; - auto newString = AllocStringObject(vm, srcLength, true); - Span data(src->GetDataUtf8Writable(), srcLength); + auto newString = CreateLineString(vm, srcLength, true); + Span data(srcFlat->GetDataUtf8Writable(), srcLength); auto newStringPtr = newString->GetDataUtf8Writable(); for (uint32_t index = 0; index < srcLength; ++index) { if (base::StringHelper::Utf8CharInRange(data[index], start, end)) { @@ -663,17 +786,18 @@ EcmaString *EcmaString::ToLower(const EcmaVM *vm, const JSHandle &sr /* static */ EcmaString *EcmaString::ToUpper(const EcmaVM *vm, const JSHandle &src) { - uint32_t srcLength = src->GetLength(); + auto srcFlat = JSHandle(vm->GetJSThread(), Flatten(vm, src)); + uint32_t srcLength = srcFlat->GetLength(); auto factory = vm->GetFactory(); - if (src->IsUtf16()) { - std::u16string u16str = base::StringHelper::Utf16ToU16String(src->GetDataUtf16(), srcLength); + if (srcFlat->IsUtf16()) { + std::u16string u16str = base::StringHelper::Utf16ToU16String(srcFlat->GetDataUtf16(), srcLength); std::string res = base::StringHelper::ToUpper(u16str); return *(factory->NewFromStdString(res)); } else { const char start = 'a'; const char end = 'z'; - auto newString = AllocStringObject(vm, srcLength, true); - Span data(src->GetDataUtf8Writable(), srcLength); + auto newString = CreateLineString(vm, srcLength, true); + Span data(srcFlat->GetDataUtf8Writable(), srcLength); auto newStringPtr = newString->GetDataUtf8Writable(); for (uint32_t index = 0; index < srcLength; ++index) { if (base::StringHelper::Utf8CharInRange(data[index], start, end)) { @@ -690,7 +814,8 @@ EcmaString *EcmaString::ToUpper(const EcmaVM *vm, const JSHandle &sr EcmaString *EcmaString::ToLocaleLower(const EcmaVM *vm, const JSHandle &src, const icu::Locale &locale) { auto factory = vm->GetFactory(); - std::u16string utf16 = src->ToU16String(); + auto srcFlat = JSHandle(vm->GetJSThread(), Flatten(vm, src)); + std::u16string utf16 = srcFlat->ToU16String(); std::string res = base::StringHelper::ToLocaleLower(utf16, locale); return *(factory->NewFromStdString(res)); } @@ -699,26 +824,125 @@ EcmaString *EcmaString::ToLocaleLower(const EcmaVM *vm, const JSHandle &src, const icu::Locale &locale) { auto factory = vm->GetFactory(); - std::u16string utf16 = src->ToU16String(); + auto srcFlat = JSHandle(vm->GetJSThread(), Flatten(vm, src)); + std::u16string utf16 = srcFlat->ToU16String(); std::string res = base::StringHelper::ToLocaleUpper(utf16, locale); return *(factory->NewFromStdString(res)); } EcmaString *EcmaString::Trim(const JSThread *thread, const JSHandle &src, TrimMode mode) { - uint32_t srcLen = src->GetLength(); + auto srcFlat = JSHandle(thread, Flatten(thread->GetEcmaVM(), src)); + uint32_t srcLen = srcFlat->GetLength(); if (UNLIKELY(srcLen == 0)) { return EcmaString::Cast(thread->GlobalConstants()->GetEmptyString().GetTaggedObject()); } - if (src->IsUtf8()) { - Span data(src->GetDataUtf8(), srcLen); - return TrimBody(thread, src, data, mode); + if (srcFlat->IsUtf8()) { + Span data(srcFlat->GetDataUtf8(), srcLen); + return TrimBody(thread, srcFlat, data, mode); } else { - Span data(src->GetDataUtf16(), srcLen); - return TrimBody(thread, src, data, mode); + Span data(srcFlat->GetDataUtf16(), srcLen); + return TrimBody(thread, srcFlat, data, mode); } } +EcmaString *EcmaString::SlowFlatten(const EcmaVM *vm, const JSHandle &string) +{ + auto thread = vm->GetJSThread(); + ASSERT(EcmaString::Cast(string->GetSecond())->GetLength() != 0); + + uint32_t length = string->GetLength(); + EcmaString *result = nullptr; + if (string->IsUtf8()) { + result = CreateLineString(vm, length, true); + WriteToFlat(*string, result->GetDataUtf8Writable(), length); + } else { + result = CreateLineString(vm, length, false); + WriteToFlat(*string, result->GetDataUtf16Writable(), length); + } + string->SetFirst(thread, JSTaggedValue(result)); + string->SetSecond(thread, JSTaggedValue(*vm->GetFactory()->GetEmptyString())); + return result; +} + +EcmaString *EcmaString::Flatten(const EcmaVM *vm, const JSHandle &string) +{ + EcmaString *s = *string; + if (s->IsLineString()) { + return s; + } + if (s->IsTreeString()) { + JSHandle tree = JSHandle::Cast(string); + if (!tree->IsFlat()) { + return SlowFlatten(vm, tree); + } + s = EcmaString::Cast(tree->GetFirst()); + } + return s; +} + +EcmaString *EcmaString::FlattenNoGC(const EcmaVM *vm, EcmaString *string) +{ + DISALLOW_GARBAGE_COLLECTION; + if (string->IsLineString()) { + return string; + } + if (string->IsTreeString()) { + TreeEcmaString *tree = TreeEcmaString::Cast(string); + if (tree->IsFlat()) { + string = EcmaString::Cast(tree->GetFirst()); + } else { + uint32_t length = tree->GetLength(); + EcmaString *result = nullptr; + if (tree->IsUtf8()) { + result = CreateLineStringNoGC(vm, length, true); + WriteToFlat(tree, result->GetDataUtf8Writable(), length); + } else { + result = CreateLineStringNoGC(vm, length, false); + WriteToFlat(tree, result->GetDataUtf16Writable(), length); + } + tree->SetFirst(vm->GetJSThread(), JSTaggedValue(result)); + tree->SetSecond(vm->GetJSThread(), JSTaggedValue(*vm->GetFactory()->GetEmptyString())); + return result; + } + } + return string; +} + +const uint8_t *EcmaString::GetUtf8DataFlat(const EcmaString *src, CVector &buf) +{ + ASSERT(src->IsUtf8()); + uint32_t length = src->GetLength(); + EcmaString *string = const_cast(src); + if (string->IsTreeString()) { + if (string->IsFlat()) { + string = EcmaString::Cast(TreeEcmaString::Cast(string)->GetFirst()); + } else { + buf.reserve(length); + WriteToFlat(string, buf.data(), length); + return buf.data(); + } + } + return string->GetDataUtf8(); +} + +const uint16_t *EcmaString::GetUtf16DataFlat(const EcmaString *src, CVector &buf) +{ + ASSERT(src->IsUtf16()); + uint32_t length = src->GetLength(); + EcmaString *string = const_cast(src); + if (string->IsTreeString()) { + if (string->IsFlat()) { + string = EcmaString::Cast(TreeEcmaString::Cast(string)->GetFirst()); + } else { + buf.reserve(length); + WriteToFlat(string, buf.data(), length); + return buf.data(); + } + } + return string->GetDataUtf16(); +} + EcmaStringAccessor::EcmaStringAccessor(EcmaString *string) { ASSERT(string != nullptr); @@ -748,7 +972,7 @@ std::string EcmaStringAccessor::ToStdString(StringConvertedUsage usage) return ""; } bool modify = (usage != StringConvertedUsage::PRINT); - [[maybe_unused]] CVector buf; + CVector buf; Span sp = string_->ToUtf8Span(buf, modify); std::string res; res.reserve(sp.size()); @@ -764,7 +988,7 @@ CString EcmaStringAccessor::ToCString(StringConvertedUsage usage) return ""; } bool modify = (usage != StringConvertedUsage::PRINT); - [[maybe_unused]] CVector buf; + CVector buf; Span sp = string_->ToUtf8Span(buf, modify); CString res; res.reserve(sp.size()); diff --git a/ecmascript/ecma_string.h b/ecmascript/ecma_string.h index cb59baced6..62d19b536e 100644 --- a/ecmascript/ecma_string.h +++ b/ecmascript/ecma_string.h @@ -22,6 +22,7 @@ #include "ecmascript/base/utf_helper.h" #include "ecmascript/ecma_macros.h" +#include "ecmascript/js_hclass.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/mem/barriers.h" #include "ecmascript/mem/space.h" @@ -36,10 +37,11 @@ namespace ecmascript { template class JSHandle; class EcmaVM; +class LineEcmaString; +class TreeEcmaString; + class EcmaString : public TaggedObject { public: - friend class EcmaStringAccessor; - CAST_CHECK(EcmaString, IsString); static constexpr uint32_t STRING_COMPRESSED_BIT = 0x1; @@ -49,9 +51,6 @@ public: // In last bit of mix_length we store if this string is compressed or not. ACCESSORS_PRIMITIVE_FIELD(MixLength, uint32_t, MIX_LENGTH_OFFSET, HASHCODE_OFFSET) ACCESSORS_PRIMITIVE_FIELD(RawHashcode, uint32_t, HASHCODE_OFFSET, SIZE) - // DATA_OFFSET: the string data stored after the string header. - // 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 enum CompressedStatus { STRING_COMPRESSED, @@ -65,85 +64,154 @@ public: }; private: + friend class EcmaStringAccessor; + friend class LineEcmaString; + friend class TreeEcmaString; + static EcmaString *CreateEmptyString(const EcmaVM *vm); - static EcmaString *CreateFromUtf8(const EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf8Len, bool canBeCompress, - MemSpaceType type = MemSpaceType::SEMI_SPACE); + static EcmaString *CreateFromUtf8(const EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf8Len, + bool canBeCompress, MemSpaceType type = MemSpaceType::SEMI_SPACE); static EcmaString *CreateFromUtf16(const EcmaVM *vm, const uint16_t *utf16Data, uint32_t utf16Len, - bool canBeCompress, MemSpaceType type = MemSpaceType::SEMI_SPACE); + bool canBeCompress, MemSpaceType type = MemSpaceType::SEMI_SPACE); + static EcmaString *CreateLineString(const EcmaVM *vm, size_t length, bool compressed); + static EcmaString *CreateLineStringNoGC(const EcmaVM *vm, size_t length, bool compressed); + static EcmaString *CreateLineStringWithSpaceType(const EcmaVM *vm, + size_t length, bool compressed, MemSpaceType type); + static EcmaString *CreateTreeString(const EcmaVM *vm, + const JSHandle &left, const JSHandle &right, uint32_t length, bool compressed); + static EcmaString *Concat(const EcmaVM *vm, - const JSHandle &str1Handle, const JSHandle &str2Handle); + const JSHandle &left, const JSHandle &right); static EcmaString *FastSubString(const EcmaVM *vm, const JSHandle &src, uint32_t start, uint32_t length); - - template - uint16_t At(int32_t index) const; - - static int32_t Compare(EcmaString *lhs, EcmaString *rhs); - - bool IsUtf16() const - { - return (GetMixLength() & STRING_COMPRESSED_BIT) == STRING_UNCOMPRESSED; - } + // require src is LineString + // not change src data structure + static inline EcmaString *FastSubUtf8String(const EcmaVM *vm, + const JSHandle &src, uint32_t start, uint32_t length); + // require src is LineString + // not change src data structure + static inline EcmaString *FastSubUtf16String(const EcmaVM *vm, + const JSHandle &src, uint32_t start, uint32_t length); bool IsUtf8() const { return (GetMixLength() & STRING_COMPRESSED_BIT) == STRING_COMPRESSED; } - static size_t ComputeDataSizeUtf16(uint32_t length) + bool IsUtf16() const { - return length * sizeof(uint16_t); + return (GetMixLength() & STRING_COMPRESSED_BIT) == STRING_UNCOMPRESSED; } - /** - * Methods for uncompressed strings (UTF16): - */ - static size_t ComputeSizeUtf16(uint32_t utf16Len) + // require is LineString + inline uint16_t *GetData() const; + inline const uint8_t *GetDataUtf8() const; + inline const uint16_t *GetDataUtf16() const; + + // require is LineString + inline uint8_t *GetDataUtf8Writable(); + inline uint16_t *GetDataUtf16Writable(); + + uint32_t GetLength() const { - return DATA_OFFSET + ComputeDataSizeUtf16(utf16Len); + return GetMixLength() >> 2U; } - inline uint16_t *GetData() const + void SetLength(uint32_t length, bool compressed = false) { - return reinterpret_cast(ToUintPtr(this) + DATA_OFFSET); + ASSERT(length < 0x40000000U); + // Use 0u for compressed/utf8 expression + SetMixLength((length << 2U) | (compressed ? STRING_COMPRESSED : STRING_UNCOMPRESSED)); } - const uint16_t *GetDataUtf16() const + inline size_t GetUtf8Length(bool modify = true) const; + + void SetIsInternString() { - LOG_ECMA_IF(!IsUtf16(), FATAL) << "EcmaString: Read data as utf16 for utf8 string"; - return GetData(); + SetMixLength(GetMixLength() | STRING_INTERN_BIT); } - /** - * Methods for compresses strings (UTF8 or LATIN1): - */ - static size_t ComputeSizeUtf8(uint32_t utf8Len) + bool IsInternString() const { - return DATA_OFFSET + utf8Len; + return (GetMixLength() & STRING_INTERN_BIT) != 0; } - /** - * It's Utf8 format, but without 0 in the end. - */ - const uint8_t *GetDataUtf8() const + void ClearInternStringFlag() { - ASSERT_PRINT(IsUtf8(), "EcmaString: Read data as utf8 for utf16 string"); - return reinterpret_cast(GetData()); + SetMixLength(GetMixLength() & ~STRING_INTERN_BIT); } - size_t GetUtf8Length(bool modify = true) const + bool TryGetHashCode(uint32_t *hash) { - if (!IsUtf16()) { - return GetLength() + 1; // add place for zero in the end + uint32_t hashcode = GetRawHashcode(); + if (hashcode == 0 && GetLength() != 0) { + return false; } - return base::utf_helper::Utf16ToUtf8Size(GetData(), GetLength(), modify); + *hash = hashcode; + return true; } - size_t GetUtf16Length() const + // not change this data structure. + // if string is not flat, this func has low efficiency. + uint32_t PUBLIC_API GetHashcode() { - return GetLength(); + uint32_t hashcode = GetRawHashcode(); + // GetLength() == 0 means it's an empty array.No need to computeHashCode again when hashseed is 0. + if (hashcode == 0 && GetLength() != 0) { + hashcode = ComputeHashcode(0); + SetRawHashcode(hashcode); + } + return hashcode; } + // not change this data structure. + // if string is not flat, this func has low efficiency. + uint32_t PUBLIC_API ComputeHashcode(uint32_t hashSeed) const; + + static uint32_t ComputeHashcodeUtf8(const uint8_t *utf8Data, size_t utf8Len, bool canBeCompress); + static uint32_t ComputeHashcodeUtf16(const uint16_t *utf16Data, uint32_t length); + + template + uint16_t At(int32_t index) const; + + // require is LineString + void WriteData(uint32_t index, uint16_t src); + + // can change left and right data structure + static int32_t Compare(const EcmaVM *vm, const JSHandle &left, const JSHandle &right); + + template + // Check that two spans are equal. Should have the same length. + static bool StringsAreEquals(Span &str1, Span &str2); + // Converts utf8Data to utf16 and compare it with given utf16_data. + static bool IsUtf8EqualsUtf16(const uint8_t *utf8Data, size_t utf8Len, const uint16_t *utf16Data, + uint32_t utf16Len); + // Compares string1 + string2 by bytes, It doesn't check canonical unicode equivalence. + bool EqualToSplicedString(const EcmaString *str1, const EcmaString *str2); + // Compares strings by bytes, It doesn't check canonical unicode equivalence. + static bool StringsAreEqual(const EcmaVM *vm, const JSHandle &str1, const JSHandle &str2); + // Compares strings by bytes, It doesn't check canonical unicode equivalence. + static bool StringsAreEqual(EcmaString *str1, EcmaString *str2); + // Two strings have the same type of utf encoding format. + static bool StringsAreEqualSameUtfEncoding(EcmaString *str1, EcmaString *str2); + // Compares strings by bytes, It doesn't check canonical unicode equivalence. + // not change str1 data structure. + // if str1 is not flat, this func has low efficiency. + static bool StringsAreEqualUtf8(const EcmaString *str1, const uint8_t *utf8Data, uint32_t utf8Len, + bool canBeCompress); + // Compares strings by bytes, It doesn't check canonical unicode equivalence. + // not change str1 data structure. + // if str1 is not flat, this func has low efficiency. + static bool StringsAreEqualUtf16(const EcmaString *str1, const uint16_t *utf16Data, uint32_t utf16Len); + + // can change receiver and search data structure + static int32_t IndexOf(const EcmaVM *vm, + const JSHandle &receiver, const JSHandle &search, int pos = 0); + + // can change receiver and search data structure + static int32_t LastIndexOf(const EcmaVM *vm, + const JSHandle &receiver, const JSHandle &search, int pos = 0); + inline size_t CopyDataUtf8(uint8_t *buf, size_t maxLength, bool modify = true) const { if (maxLength == 0) { @@ -184,24 +252,28 @@ private: } // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) // Only memcpy_s maxLength number of chars into buffer if length > maxLength + CVector tmpBuf; + const uint8_t *data = GetUtf8DataFlat(this, tmpBuf); if (length > maxLength) { - if (memcpy_s(buf, maxLength, GetDataUtf8() + start, maxLength) != EOK) { + if (memcpy_s(buf, maxLength, data + start, maxLength) != EOK) { LOG_FULL(FATAL) << "memcpy_s failed when length > maxlength"; UNREACHABLE(); } return maxLength; } - if (memcpy_s(buf, maxLength, GetDataUtf8() + start, length) != EOK) { + if (memcpy_s(buf, maxLength, data + start, length) != EOK) { LOG_FULL(FATAL) << "memcpy_s failed when length <= maxlength"; UNREACHABLE(); } return length; } + CVector tmpBuf; + const uint16_t *data = GetUtf16DataFlat(this, tmpBuf); if (length > maxLength) { - return base::utf_helper::ConvertRegionUtf16ToUtf8(GetDataUtf16(), buf, maxLength, maxLength, start, + return base::utf_helper::ConvertRegionUtf16ToUtf8(data, buf, maxLength, maxLength, start, modify, isWriteBuffer); } - return base::utf_helper::ConvertRegionUtf16ToUtf8(GetDataUtf16(), buf, length, maxLength, start, + return base::utf_helper::ConvertRegionUtf16ToUtf8(data, buf, length, maxLength, start, modify, isWriteBuffer); } @@ -221,14 +293,18 @@ private: } if (IsUtf16()) { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - if (memcpy_s(buf, ComputeDataSizeUtf16(maxLength), GetDataUtf16() + start, ComputeDataSizeUtf16(length)) != + CVector tmpBuf; + const uint16_t *data = EcmaString::GetUtf16DataFlat(this, tmpBuf); + if (memcpy_s(buf, maxLength * sizeof(uint16_t), data + start, length * sizeof(uint16_t)) != EOK) { LOG_FULL(FATAL) << "memcpy_s failed"; UNREACHABLE(); } return length; } - return base::utf_helper::ConvertRegionUtf8ToUtf16(GetDataUtf8(), buf, len, maxLength, start); + CVector tmpBuf; + const uint8_t *data = EcmaString::GetUtf8DataFlat(this, tmpBuf); + return base::utf_helper::ConvertRegionUtf8ToUtf16(data, buf, len, maxLength, start); } std::u16string ToU16String(uint32_t len = 0); @@ -238,7 +314,7 @@ private: uint8_t *buf = nullptr; auto length = GetLength(); if (IsUtf16()) { - auto size = ComputeDataSizeUtf16(length); + auto size = length * sizeof(uint16_t); buf = new uint8_t[size](); CopyDataUtf16(reinterpret_cast(buf), length); } else { @@ -248,147 +324,98 @@ private: return std::unique_ptr(buf); } - Span ToUtf8Span([[maybe_unused]] CVector &buf, bool modify = true) + Span ToUtf8Span(CVector &buf, bool modify = true) { Span str; uint32_t strLen = GetLength(); if (UNLIKELY(IsUtf16())) { - size_t len = base::utf_helper::Utf16ToUtf8Size(GetDataUtf16(), strLen, modify) - 1; + CVector tmpBuf; + const uint16_t *data = EcmaString::GetUtf16DataFlat(this, tmpBuf); + size_t len = base::utf_helper::Utf16ToUtf8Size(data, strLen, modify) - 1; buf.reserve(len); - len = base::utf_helper::ConvertRegionUtf16ToUtf8(GetDataUtf16(), buf.data(), strLen, len, 0, modify); + len = base::utf_helper::ConvertRegionUtf16ToUtf8(data, buf.data(), strLen, len, 0, modify); str = Span(buf.data(), len); } else { - str = Span(GetDataUtf8(), strLen); + const uint8_t *data = EcmaString::GetUtf8DataFlat(this, buf); + str = Span(data, strLen); } return str; } - void WriteData(EcmaString *src, uint32_t start, uint32_t destSize, uint32_t length) - { - if (IsUtf8()) { - ASSERT(src->IsUtf8()); - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - if (length != 0 && memcpy_s(GetDataUtf8Writable() + start, destSize, src->GetDataUtf8(), length) != EOK) { - LOG_FULL(FATAL) << "memcpy_s failed"; - UNREACHABLE(); - } - } else if (src->IsUtf8()) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - Span to(GetDataUtf16Writable() + start, length); - Span from(src->GetDataUtf8(), length); - for (uint32_t i = 0; i < length; i++) { - to[i] = from[i]; - } - } else { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - if (length != 0 && memcpy_s(GetDataUtf16Writable() + start, - ComputeDataSizeUtf16(destSize), src->GetDataUtf16(), ComputeDataSizeUtf16(length)) != EOK) { - LOG_FULL(FATAL) << "memcpy_s failed"; - UNREACHABLE(); - } - } - } - - inline void WriteData(uint16_t src, uint32_t start) - { - if (IsUtf8()) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - *(GetDataUtf8Writable() + start) = static_cast(src); - } else { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - *(GetDataUtf16Writable() + start) = src; - } - } - - uint32_t GetLength() const - { - return GetMixLength() >> 2U; - } - - void SetIsInternString() - { - SetMixLength(GetMixLength() | STRING_INTERN_BIT); - } - - bool IsInternString() const - { - return (GetMixLength() & STRING_INTERN_BIT) != 0; - } - - void ClearInternStringFlag() - { - SetMixLength(GetMixLength() & ~STRING_INTERN_BIT); - } - - size_t ObjectSize() const - { - uint32_t length = GetLength(); - return IsUtf16() ? ComputeSizeUtf16(length) : ComputeSizeUtf8(length); - } - - uint32_t PUBLIC_API GetHashcode() - { - uint32_t hashcode = GetRawHashcode(); - // GetLength() == 0 means it's an empty array.No need to computeHashCode again when hashseed is 0. - if (hashcode == 0 && GetLength() != 0) { - hashcode = ComputeHashcode(0); - SetRawHashcode(hashcode); - } - return hashcode; - } - - uint32_t PUBLIC_API ComputeHashcode(uint32_t hashSeed) const; - - static int32_t IndexOf(EcmaString *lhs, EcmaString *rhs, int pos = 0); - - static int32_t LastIndexOf(EcmaString *lhs, EcmaString *rhs, int pos = 0); - - static constexpr uint32_t GetStringCompressionMask() - { - return STRING_COMPRESSED_BIT; - } - - /** - * Compares string1 + string2 by bytes, It doesn't check canonical unicode equivalence. - */ - bool EqualToSplicedString(const EcmaString *str1, const EcmaString *str2); - /** - * Compares strings by bytes, It doesn't check canonical unicode equivalence. - */ - static bool StringsAreEqual(EcmaString *str1, EcmaString *str2); - /** - * Two strings have the same type of utf encoding format. - */ - static bool StringsAreEqualSameUtfEncoding(EcmaString *str1, EcmaString *str2); - /** - * Compares strings by bytes, It doesn't check canonical unicode equivalence. - */ - static bool StringsAreEqualUtf8(const EcmaString *str1, const uint8_t *utf8Data, uint32_t utf8Len, - bool canBeCompress); - /** - * Compares strings by bytes, It doesn't check canonical unicode equivalence. - */ - static bool StringsAreEqualUtf16(const EcmaString *str1, const uint16_t *utf16Data, uint32_t utf16Len); - static uint32_t ComputeHashcodeUtf8(const uint8_t *utf8Data, size_t utf8Len, bool canBeCompress); - static uint32_t ComputeHashcodeUtf16(const uint16_t *utf16Data, uint32_t length); - - static EcmaString *AllocStringObject(const EcmaVM *vm, size_t length, bool compressed); - static EcmaString *AllocStringObjectWithSpaceType(const EcmaVM *vm, size_t length, bool compressed, - MemSpaceType type); + void WriteData(EcmaString *src, uint32_t start, uint32_t destSize, uint32_t length); static bool CanBeCompressed(const uint8_t *utf8Data, uint32_t utf8Len); static bool CanBeCompressed(const uint16_t *utf16Data, uint32_t utf16Len); static bool CanBeCompressed(const EcmaString *string); - static inline EcmaString *FastSubUtf8String(const EcmaVM *vm, const JSHandle &src, uint32_t start, - uint32_t length); - static inline EcmaString *FastSubUtf16String(const EcmaVM *vm, const JSHandle &src, uint32_t start, - uint32_t length); - bool ToElementIndex(uint32_t *index); bool ToTypedArrayIndex(uint32_t *index); + template + static EcmaString *ConvertCase(const EcmaVM *vm, const JSHandle &src); + + template + static EcmaString *LocaleConvertCase(const EcmaVM *vm, const JSHandle &src, const icu::Locale &locale); + + template + static EcmaString *TrimBody(const JSThread *thread, const JSHandle &src, Span &data, TrimMode mode); + + static EcmaString *Trim(const JSThread *thread, const JSHandle &src, TrimMode mode = TrimMode::TRIM); + + // single char copy for loop + template + static void CopyChars(DstType *dst, SrcType *src, uint32_t count); + + // memory block copy + template + static bool MemCopyChars(Span &dst, size_t dstMax, Span &src, size_t count); + + static bool IsASCIICharacter(uint16_t data) + { + // \0 is not considered ASCII in Ecma-Modified-UTF8 [only modify '\u0000'] + return data - 1U < base::utf_helper::UTF8_1B_MAX; + } + + template + static int32_t IndexOf(Span &lhsSp, Span &rhsSp, int32_t pos, int32_t max); + + template + static int32_t LastIndexOf(Span &lhsSp, Span &rhsSp, int32_t pos); + + bool IsFlat() const; + + bool IsLineString() const + { + return GetClass()->IsLineString(); + } + + bool IsTreeString() const + { + return GetClass()->IsTreeString(); + } + + JSType GetStringType() const + { + JSType type = GetClass()->GetObjectType(); + ASSERT(type >= JSType::STRING_FIRST && type <= JSType::STRING_LAST); + return type; + } + + template + static void WriteToFlat(EcmaString *src, Char *buf, uint32_t maxLength); + + static const uint8_t *GetUtf8DataFlat(const EcmaString *src, CVector &buf); + + static const uint16_t *GetUtf16DataFlat(const EcmaString *src, CVector &buf); + + // string must be not flat + static EcmaString *SlowFlatten(const EcmaVM *vm, const JSHandle &string); + + static EcmaString *Flatten(const EcmaVM *vm, const JSHandle &string); + + static EcmaString *FlattenNoGC(const EcmaVM *vm, EcmaString *string); + static EcmaString *ToLower(const EcmaVM *vm, const JSHandle &src); static EcmaString *ToUpper(const EcmaVM *vm, const JSHandle &src); @@ -396,66 +423,97 @@ private: static EcmaString *ToLocaleLower(const EcmaVM *vm, const JSHandle &src, const icu::Locale &locale); static EcmaString *ToLocaleUpper(const EcmaVM *vm, const JSHandle &src, const icu::Locale &locale); - - template - static EcmaString *TrimBody(const JSThread *thread, const JSHandle &src, Span &data, TrimMode mode); - - static EcmaString *Trim(const JSThread *thread, const JSHandle &src, TrimMode mode = TrimMode::TRIM); - - void SetLength(uint32_t length, bool compressed = false) - { - ASSERT(length < 0x40000000U); - // Use 0u for compressed/utf8 expression - SetMixLength((length << 2U) | (compressed ? STRING_COMPRESSED : STRING_UNCOMPRESSED)); - } - - uint16_t *GetDataUtf16Writable() - { - LOG_ECMA_IF(!IsUtf16(), FATAL) << "EcmaString: Read data as utf16 for utf8 string"; - return GetData(); - } - - uint8_t *GetDataUtf8Writable() - { - ASSERT_PRINT(IsUtf8(), "EcmaString: Read data as utf8 for utf16 string"); - return reinterpret_cast(GetData()); - } - - static void CopyUtf16AsUtf8(const uint16_t *utf16From, uint8_t *utf8To, uint32_t utf16Len); - - static bool IsASCIICharacter(uint16_t data) - { - // \0 is not considered ASCII in Ecma-Modified-UTF8 [only modify '\u0000'] - return data - 1U < base::utf_helper::UTF8_1B_MAX; - } - - /** - * str1 should have the same length as utf16_data. - * Converts utf8Data to utf16 and compare it with given utf16_data. - */ - static bool IsUtf8EqualsUtf16(const uint8_t *utf8Data, size_t utf8Len, const uint16_t *utf16Data, - uint32_t utf16Len); - - template - /** - * Check that two spans are equal. Should have the same length. - */ - static bool StringsAreEquals(Span &str1, Span &str2); - - template - /** - * Copy String from src to dst - * */ - static bool StringCopy(Span &dst, size_t dstMax, Span &src, size_t count); - - template - static int32_t IndexOf(Span &lhsSp, Span &rhsSp, int32_t pos, int32_t max); - - template - static int32_t LastIndexOf(Span &lhsSp, Span &rhsSp, int32_t pos); }; -static_assert((EcmaString::DATA_OFFSET % static_cast(MemAlignment::MEM_ALIGN_OBJECT)) == 0); +// The LineEcmaString abstract class captures sequential string values, only LineEcmaString can store chars data +class LineEcmaString : public EcmaString { +public: + // DATA_OFFSET: the string data stored after the string header. + // Data can be stored in utf8 or utf16 form according to compressed bit. + static constexpr size_t DATA_OFFSET = EcmaString::SIZE; // DATA_OFFSET equal to Empty String size + + CAST_CHECK(LineEcmaString, IsLineString); + + static LineEcmaString *Cast(EcmaString *str) + { + return static_cast(str); + } + + static LineEcmaString *Cast(const EcmaString *str) + { + return LineEcmaString::Cast(const_cast(str)); + } + + static size_t ComputeSizeUtf8(uint32_t utf8Len) + { + return DATA_OFFSET + utf8Len; + } + + static size_t ComputeSizeUtf16(uint32_t utf16Len) + { + return DATA_OFFSET + utf16Len * sizeof(uint16_t); + } + + static size_t ObjectSize(EcmaString *str) + { + uint32_t length = str->GetLength(); + return str->IsUtf16() ? ComputeSizeUtf16(length) : ComputeSizeUtf8(length); + } + + uint16_t *GetData() const + { + return reinterpret_cast(ToUintPtr(this) + DATA_OFFSET); + } + + template + uint16_t Get(int32_t index) const; + + void Set(uint32_t index, uint16_t src) + { + ASSERT(index < GetLength()); + if (IsUtf8()) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + *(reinterpret_cast(GetData()) + index) = static_cast(src); + } else { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + *(GetData() + index) = src; + } + } +}; +static_assert((LineEcmaString::DATA_OFFSET % static_cast(MemAlignment::MEM_ALIGN_OBJECT)) == 0); + +class TreeEcmaString : public EcmaString { +public: + // Minimum length for a tree string + static constexpr uint32_t MIN_TREE_ECMASTRING_LENGTH = 13; + + static constexpr size_t FIRST_OFFSET = EcmaString::SIZE; + ACCESSORS(First, FIRST_OFFSET, SECOND_OFFSET); + ACCESSORS(Second, SECOND_OFFSET, SIZE); + + DECL_VISIT_OBJECT(FIRST_OFFSET, SIZE); + + CAST_CHECK(TreeEcmaString, IsTreeString); + + static TreeEcmaString *Cast(EcmaString *str) + { + return static_cast(str); + } + + static TreeEcmaString *Cast(const EcmaString *str) + { + return TreeEcmaString::Cast(const_cast(str)); + } + + bool IsFlat() const + { + auto strSecond = EcmaString::Cast(GetSecond()); + return strSecond->GetLength() == 0; + } + + template + uint16_t Get(int32_t index) const; +}; // if you want to use functions of EcmaString, please not use directly, // and use functions of EcmaStringAccessor alternatively. @@ -470,9 +528,9 @@ public: explicit EcmaStringAccessor(const JSHandle &strHandle); - static EcmaString *AllocStringObject(const EcmaVM *vm, size_t length, bool compressed) + static EcmaString *CreateLineString(const EcmaVM *vm, size_t length, bool compressed) { - return EcmaString::AllocStringObject(vm, length, compressed); + return EcmaString::CreateLineString(vm, length, compressed); } static EcmaString *CreateEmptyString(const EcmaVM *vm) @@ -498,6 +556,7 @@ public: return EcmaString::Concat(vm, str1Handle, str2Handle); } + // can change src data structure static EcmaString *FastSubString(const EcmaVM *vm, const JSHandle &src, uint32_t start, uint32_t length) { @@ -519,14 +578,22 @@ public: return string_->GetLength(); } - size_t GetUtf8Length() const - { - return string_->GetUtf8Length(); - } + // require is LineString + inline size_t GetUtf8Length() const; size_t ObjectSize() const { - return string_->ObjectSize(); + if (string_->IsLineString()) { + return LineEcmaString::ObjectSize(string_); + } else { + return TreeEcmaString::SIZE; + } + } + + // For TreeString, the calculation result is size of LineString correspondingly. + size_t GetFlatStringSize() const + { + return LineEcmaString::ObjectSize(string_); } bool IsInternString() const @@ -544,66 +611,84 @@ public: string_->ClearInternStringFlag(); } - const uint8_t *GetDataUtf8() - { - return string_->GetDataUtf8(); - } + // require is LineString + // It's Utf8 format, but without 0 in the end. + inline const uint8_t *GetDataUtf8(); - const uint16_t *GetDataUtf16() - { - return string_->GetDataUtf16(); - } + // require is LineString + inline const uint16_t *GetDataUtf16(); + // not change string data structure. + // if string is not flat, this func has low efficiency. std::u16string ToU16String(uint32_t len = 0) { return string_->ToU16String(len); } + // not change string data structure. + // if string is not flat, this func has low efficiency. std::unique_ptr ToOneByteDataForced() { return string_->ToOneByteDataForced(); } - Span ToUtf8Span([[maybe_unused]] CVector &buf) + // not change string data structure. + // if string is not flat, this func has low efficiency. + Span ToUtf8Span(CVector &buf) { return string_->ToUtf8Span(buf); } + // not change string data structure. + // if string is not flat, this func has low efficiency. std::string ToStdString(StringConvertedUsage usage = StringConvertedUsage::PRINT); + // not change string data structure. + // if string is not flat, this func has low efficiency. CString ToCString(StringConvertedUsage usage = StringConvertedUsage::LOGICOPERATION); + // not change string data structure. + // if string is not flat, this func has low efficiency. uint32_t WriteToFlatUtf8(uint8_t *buf, uint32_t maxLength, bool isWriteBuffer = false) { return string_->WriteUtf8(buf, maxLength, isWriteBuffer); } + // not change string data structure. + // if string is not flat, this func has low efficiency. uint32_t WriteToFlatUtf16(uint16_t *buf, uint32_t maxLength) const { return string_->CopyDataUtf16(buf, maxLength); } - static void ReadData(EcmaString * dst, EcmaString *src, uint32_t start, uint32_t destSize, uint32_t length) - { - dst->WriteData(src, start, destSize, length); - } + // require dst is LineString + // not change src data structure. + // if src is not flat, this func has low efficiency. + inline static void ReadData(EcmaString * dst, EcmaString *src, uint32_t start, uint32_t destSize, uint32_t length); + // not change src data structure. + // if src is not flat, this func has low efficiency. template uint16_t Get(uint32_t index) const { return string_->At(index); } + // require string is LineString. void Set(uint32_t index, uint16_t src) { - return string_->WriteData(src, index); + return string_->WriteData(index, src); } + // not change src data structure. + // if src is not flat, this func has low efficiency. uint32_t GetHashcode() { return string_->GetHashcode(); } + // not change src data structure. + // if src is not flat, this func has low efficiency. uint32_t ComputeHashcode(uint32_t hashSeed) { return string_->ComputeHashcode(hashSeed); @@ -619,42 +704,64 @@ public: return EcmaString::ComputeHashcodeUtf16(utf16Data, length); } - static int32_t IndexOf(EcmaString *lhs, EcmaString *rhs, int pos = 0) + // can change receiver and search data structure + static int32_t IndexOf(const EcmaVM *vm, + const JSHandle &receiver, const JSHandle &search, int pos = 0) { - return EcmaString::IndexOf(lhs, rhs, pos); + return EcmaString::IndexOf(vm, receiver, search, pos); } - static int32_t LastIndexOf(EcmaString *lhs, EcmaString *rhs, int pos = 0) + // can change receiver and search data structure + static int32_t LastIndexOf(const EcmaVM *vm, + const JSHandle &receiver, const JSHandle &search, int pos = 0) { - return EcmaString::LastIndexOf(lhs, rhs, pos); + return EcmaString::LastIndexOf(vm, receiver, search, pos); } - static int32_t Compare(EcmaString *lhs, EcmaString *rhs) + // can change receiver and search data structure + static int32_t Compare(const EcmaVM *vm, const JSHandle& left, const JSHandle& right) { - return EcmaString::Compare(lhs, rhs); + return EcmaString::Compare(vm, left, right); } + // can change str1 and str2 data structure + static bool StringsAreEqual(const EcmaVM *vm, const JSHandle &str1, const JSHandle &str2) + { + return EcmaString::StringsAreEqual(vm, str1, str2); + } + + // not change str1 and str2 data structure. + // if str1 or str2 is not flat, this func has low efficiency. static bool StringsAreEqual(EcmaString *str1, EcmaString *str2) { return EcmaString::StringsAreEqual(str1, str2); } + // not change str1 and str2 data structure. + // if str1 or str2 is not flat, this func has low efficiency. static bool StringsAreEqualSameUtfEncoding(EcmaString *str1, EcmaString *str2) { return EcmaString::StringsAreEqualSameUtfEncoding(str1, str2); } + // not change str1 data structure. + // if str1 is not flat, this func has low efficiency. static bool StringsAreEqualUtf8(const EcmaString *str1, const uint8_t *utf8Data, uint32_t utf8Len, bool canBeCompress) { return EcmaString::StringsAreEqualUtf8(str1, utf8Data, utf8Len, canBeCompress); } + // not change str1 data structure. + // if str1 is not flat, this func has low efficiency. static bool StringsAreEqualUtf16(const EcmaString *str1, const uint16_t *utf16Data, uint32_t utf16Len) { return EcmaString::StringsAreEqualUtf16(str1, utf16Data, utf16Len); } + // require str1 and str2 are LineString. + // not change string data structure. + // if string is not flat, this func has low efficiency. bool EqualToSplicedString(const EcmaString *str1, const EcmaString *str2) { return string_->EqualToSplicedString(str1, str2); @@ -670,16 +777,21 @@ public: return EcmaString::CanBeCompressed(utf16Data, utf16Len); } + // require string is LineString static bool CanBeCompressed(const EcmaString *string) { return EcmaString::CanBeCompressed(string); } + // not change string data structure. + // if string is not flat, this func has low efficiency. bool ToElementIndex(uint32_t *index) { return string_->ToElementIndex(index); } + // not change string data structure. + // if string is not flat, this func has low efficiency. bool ToTypedArrayIndex(uint32_t *index) { return string_->ToTypedArrayIndex(index); @@ -711,6 +823,46 @@ public: return EcmaString::Trim(thread, src, mode); } + bool IsFlat() const + { + return string_->IsFlat(); + } + + bool IsLineString() const + { + return string_->IsLineString(); + } + + bool IsTreeString() const + { + return string_->IsTreeString(); + } + + static EcmaString *Flatten(const EcmaVM *vm, const JSHandle &string) + { + return EcmaString::Flatten(vm, string); + } + + static EcmaString *SlowFlatten(const EcmaVM *vm, const JSHandle &string) + { + return EcmaString::SlowFlatten(vm, string); + } + + static EcmaString *FlattenNoGC(const EcmaVM *vm, EcmaString *string) + { + return EcmaString::FlattenNoGC(vm, string); + } + + static const uint8_t *GetUtf8DataFlat(const EcmaString *src, CVector &buf) + { + return EcmaString::GetUtf8DataFlat(src, buf); + } + + static const uint16_t *GetUtf16DataFlat(const EcmaString *src, CVector &buf) + { + return EcmaString::GetUtf16DataFlat(src, buf); + } + private: EcmaString *string_ {nullptr}; }; diff --git a/ecmascript/ecma_string_table.cpp b/ecmascript/ecma_string_table.cpp index 09f7246a04..0493b920d4 100644 --- a/ecmascript/ecma_string_table.cpp +++ b/ecmascript/ecma_string_table.cpp @@ -27,6 +27,7 @@ EcmaStringTable::EcmaStringTable(const EcmaVM *vm) : vm_(vm) {} EcmaString *EcmaStringTable::GetString(const JSHandle &firstString, const JSHandle &secondString) const { + ASSERT(EcmaStringAccessor(firstString).IsLineString() && EcmaStringAccessor(secondString).IsLineString()); uint32_t hashCode = EcmaStringAccessor(firstString).GetHashcode(); hashCode = EcmaStringAccessor(secondString).ComputeHashcode(hashCode); auto range = table_.equal_range(hashCode); @@ -70,6 +71,7 @@ EcmaString *EcmaStringTable::GetString(const uint16_t *utf16Data, uint32_t utf16 EcmaString *EcmaStringTable::GetString(EcmaString *string) const { + ASSERT(EcmaStringAccessor(string).IsLineString()); auto hashcode = EcmaStringAccessor(string).GetHashcode(); auto range = table_.equal_range(hashcode); auto item = range.first; @@ -87,6 +89,7 @@ void EcmaStringTable::InternString(EcmaString *string) if (EcmaStringAccessor(string).IsInternString()) { return; } + ASSERT(EcmaStringAccessor(string).IsLineString()); table_.emplace(EcmaStringAccessor(string).GetHashcode(), string); EcmaStringAccessor(string).SetInternString(); } @@ -99,12 +102,14 @@ void EcmaStringTable::InternEmptyString(EcmaString *emptyStr) EcmaString *EcmaStringTable::GetOrInternString(const JSHandle &firstString, const JSHandle &secondString) { - EcmaString *concatString = GetString(firstString, secondString); + auto firstFlat = JSHandle(vm_->GetJSThread(), EcmaStringAccessor::Flatten(vm_, firstString)); + auto secondFlat = JSHandle(vm_->GetJSThread(), EcmaStringAccessor::Flatten(vm_, secondString)); + EcmaString *concatString = GetString(firstFlat, secondFlat); if (concatString != nullptr) { return concatString; } - concatString = EcmaStringAccessor::Concat(vm_, firstString, secondString); - + JSHandle concatHandle(vm_->GetJSThread(), EcmaStringAccessor::Concat(vm_, firstFlat, secondFlat)); + concatString = EcmaStringAccessor::Flatten(vm_, concatHandle); InternString(concatString); return concatString; } @@ -149,13 +154,18 @@ EcmaString *EcmaStringTable::GetOrInternString(EcmaString *string) if (EcmaStringAccessor(string).IsInternString()) { return string; } - - EcmaString *result = GetString(string); + JSHandle strHandle(vm_->GetJSThread(), string); + // may gc + auto strFlat = EcmaStringAccessor::Flatten(vm_, strHandle); + if (EcmaStringAccessor(strFlat).IsInternString()) { + return strFlat; + } + EcmaString *result = GetString(strFlat); if (result != nullptr) { return result; } - InternString(string); - return string; + InternString(strFlat); + return strFlat; } EcmaString *EcmaStringTable::GetOrInternStringWithSpaceType(const uint8_t *utf8Data, uint32_t utf8Len, @@ -207,6 +217,9 @@ bool EcmaStringTable::CheckStringTableValidity() { for (auto itemOuter = table_.begin(); itemOuter != table_.end(); ++itemOuter) { auto outerString = itemOuter->second; + if (!EcmaStringAccessor(outerString).IsLineString()) { + return false; + } int counter = 0; auto hashcode = EcmaStringAccessor(outerString).GetHashcode(); auto range = table_.equal_range(hashcode); diff --git a/ecmascript/global_env_constants.cpp b/ecmascript/global_env_constants.cpp index 0f50194d95..c5bbd1aa1a 100644 --- a/ecmascript/global_env_constants.cpp +++ b/ecmascript/global_env_constants.cpp @@ -91,7 +91,8 @@ void GlobalEnvConstants::InitRootsClass([[maybe_unused]] JSThread *thread, JSHCl factory->NewEcmaReadOnlyHClass(hClass, FreeObject::SIZE_OFFSET, JSType::FREE_OBJECT_WITH_ONE_FIELD)); SetConstant(ConstantIndex::FREE_OBJECT_WITH_TWO_FIELD_CLASS_INDEX, factory->NewEcmaReadOnlyHClass(hClass, FreeObject::SIZE, JSType::FREE_OBJECT_WITH_TWO_FIELD)); - SetConstant(ConstantIndex::STRING_CLASS_INDEX, factory->NewEcmaReadOnlyHClass(hClass, 0, JSType::STRING)); + SetConstant(ConstantIndex::LINE_STRING_CLASS_INDEX, factory->NewEcmaReadOnlyHClass(hClass, 0, JSType::LINE_STRING)); + SetConstant(ConstantIndex::TREE_STRING_CLASS_INDEX, factory->NewEcmaReadOnlyHClass(hClass, 0, JSType::TREE_STRING)); SetConstant(ConstantIndex::ARRAY_CLASS_INDEX, factory->NewEcmaReadOnlyHClass(hClass, 0, JSType::TAGGED_ARRAY)); SetConstant(ConstantIndex::BYTE_ARRAY_CLASS_INDEX, diff --git a/ecmascript/global_env_constants.h b/ecmascript/global_env_constants.h index 5285575cf8..c3dcca60b3 100644 --- a/ecmascript/global_env_constants.h +++ b/ecmascript/global_env_constants.h @@ -35,7 +35,8 @@ class JSThread; V(JSTaggedValue, FreeObjectWithNoneFieldClass, FREE_OBJECT_WITH_NONE_FIELD_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, FreeObjectWithOneFieldClass, FREE_OBJECT_WITH_ONE_FIELD_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, FreeObjectWithTwoFieldClass, FREE_OBJECT_WITH_TWO_FIELD_CLASS_INDEX, ecma_roots_class) \ - V(JSTaggedValue, StringClass, STRING_CLASS_INDEX, ecma_roots_class) \ + V(JSTaggedValue, LineStringClass, LINE_STRING_CLASS_INDEX, ecma_roots_class) \ + V(JSTaggedValue, TreeStringClass, TREE_STRING_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, ArrayClass, ARRAY_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, ByteArrayClass, BYTE_ARRAY_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, ConstantPoolClass, CONSTANT_POOL_CLASS_INDEX, ecma_roots_class) \ diff --git a/ecmascript/ic/ic_compare_op.cpp b/ecmascript/ic/ic_compare_op.cpp index fee110bc43..4f7e6964f8 100644 --- a/ecmascript/ic/ic_compare_op.cpp +++ b/ecmascript/ic/ic_compare_op.cpp @@ -269,9 +269,9 @@ ComparisonResult CompareOp::Compare(JSThread *thread, JSTaggedValue left, break; } case CompareOpType::STRING_STRING: { - auto xString = static_cast(left.GetTaggedObject()); - auto yString = static_cast(right.GetTaggedObject()); - int result = EcmaStringAccessor::Compare(xString, yString); + JSHandle xHandle(thread, left); + JSHandle yHandle(thread, right); + int result = EcmaStringAccessor::Compare(thread->GetEcmaVM(), xHandle, yHandle); if (result < 0) { ret = ComparisonResult::LESS; } else if (result == 0) { diff --git a/ecmascript/ic/tests/ic_binaryop_test.cpp b/ecmascript/ic/tests/ic_binaryop_test.cpp index 3ac1d484a8..2654e06dfe 100644 --- a/ecmascript/ic/tests/ic_binaryop_test.cpp +++ b/ecmascript/ic/tests/ic_binaryop_test.cpp @@ -87,7 +87,7 @@ HWTEST_F_L0(ICBinaryOPTest, AddWithTSType) JSTaggedValue resInICPath3 = ICBinaryOP::AddWithTSType(thread, Str1.GetTaggedValue(), Str2.GetTaggedValue(), JSTaggedValue(static_cast(BinaryType::STRING))); ASSERT_TRUE(resInICPath3.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(*slowHandle3, reinterpret_cast(resInICPath3.GetRawData())), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVm, slowHandle3, JSHandle(thread, resInICPath3)), 0); JSTaggedValue resInSlowPath4 = SlowRuntimeStub::Add2(thread, JSTaggedValue::Undefined(), arg2.GetTaggedValue()); @@ -104,7 +104,7 @@ HWTEST_F_L0(ICBinaryOPTest, AddWithTSType) Str1.GetTaggedValue(), JSTaggedValue(static_cast(BinaryType::STRING_GEN))); ASSERT_TRUE(resInICPath5.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(*slowHandle5, reinterpret_cast(resInICPath5.GetRawData())), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVm, slowHandle5, JSHandle(thread, resInICPath5)), 0); JSTaggedValue resInSlowPath6 = SlowRuntimeStub::Add2(thread, Str1.GetTaggedValue(), JSTaggedValue::Null()); @@ -112,7 +112,7 @@ HWTEST_F_L0(ICBinaryOPTest, AddWithTSType) JSTaggedValue resInICPath6 = ICBinaryOP::AddWithTSType(thread, Str1.GetTaggedValue(), JSTaggedValue::Null(), JSTaggedValue(static_cast(BinaryType::STRING_GEN))); ASSERT_TRUE(resInICPath6.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(*slowHandle6, reinterpret_cast(resInICPath6.GetRawData())), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVm, slowHandle6, JSHandle(thread, resInICPath6)), 0); JSTaggedValue resInSlowPath7 = SlowRuntimeStub::Add2(thread, arg1.GetTaggedValue(), JSTaggedValue::True()); @@ -127,7 +127,7 @@ HWTEST_F_L0(ICBinaryOPTest, AddWithTSType) JSTaggedValue resInICPath8 = ICBinaryOP::AddWithTSType(thread, arg4.GetTaggedValue(), JSTaggedValue::Null(), JSTaggedValue(static_cast(BinaryType::GENERIC))); ASSERT_TRUE(resInICPath8.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(*slowHandle8, reinterpret_cast(resInICPath8.GetRawData())), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVm, slowHandle8, JSHandle(thread, resInICPath8)), 0); }; HWTEST_F_L0(ICBinaryOPTest, SubWithTSType) diff --git a/ecmascript/interpreter/fast_runtime_stub-inl.h b/ecmascript/interpreter/fast_runtime_stub-inl.h index b6ba34e5b4..993a69af83 100644 --- a/ecmascript/interpreter/fast_runtime_stub-inl.h +++ b/ecmascript/interpreter/fast_runtime_stub-inl.h @@ -126,36 +126,42 @@ JSTaggedValue FastRuntimeStub::FastEqual(JSTaggedValue left, JSTaggedValue right return JSTaggedValue::Hole(); } -bool FastRuntimeStub::FastStrictEqual(JSTaggedValue left, JSTaggedValue right) +JSTaggedValue FastRuntimeStub::FastStrictEqual(JSTaggedValue left, JSTaggedValue right) { if (left.IsNumber()) { if (right.IsNumber()) { double dLeft = left.IsInt() ? left.GetInt() : left.GetDouble(); double dRight = right.IsInt() ? right.GetInt() : right.GetDouble(); - return JSTaggedValue::StrictNumberEquals(dLeft, dRight); + return JSTaggedValue::StrictNumberEquals(dLeft, dRight) ? JSTaggedValue::True() : JSTaggedValue::False(); } - return false; + return JSTaggedValue::False(); } if (right.IsNumber()) { - return false; + return JSTaggedValue::False(); } if (left == right) { - return true; + return JSTaggedValue::True(); } if (left.IsString() && right.IsString()) { - return EcmaStringAccessor::StringsAreEqual(static_cast(left.GetTaggedObject()), - static_cast(right.GetTaggedObject())); + auto leftStr = static_cast(left.GetTaggedObject()); + auto rightStr = static_cast(right.GetTaggedObject()); + if (EcmaStringAccessor(leftStr).IsFlat() && EcmaStringAccessor(rightStr).IsFlat()) { + return EcmaStringAccessor::StringsAreEqual(static_cast(left.GetTaggedObject()), + static_cast(right.GetTaggedObject())) ? + JSTaggedValue::True() : JSTaggedValue::False(); + } + return JSTaggedValue::Hole(); } if (left.IsBigInt()) { if (right.IsBigInt()) { - return BigInt::Equal(left, right); + return BigInt::Equal(left, right) ? JSTaggedValue::True() : JSTaggedValue::False(); } - return false; + return JSTaggedValue::False(); } if (right.IsBigInt()) { - return false; + return JSTaggedValue::False(); } - return false; + return JSTaggedValue::False(); } bool FastRuntimeStub::IsSpecialIndexedObj(JSType jsType) diff --git a/ecmascript/interpreter/fast_runtime_stub.h b/ecmascript/interpreter/fast_runtime_stub.h index 715745baa4..2121b1aca7 100644 --- a/ecmascript/interpreter/fast_runtime_stub.h +++ b/ecmascript/interpreter/fast_runtime_stub.h @@ -32,7 +32,7 @@ public: static inline JSTaggedValue FastMod(JSTaggedValue left, JSTaggedValue right); static inline JSTaggedValue FastEqual(JSTaggedValue left, JSTaggedValue right); static inline JSTaggedValue FastTypeOf(JSThread *thread, JSTaggedValue obj); - static inline bool FastStrictEqual(JSTaggedValue left, JSTaggedValue right); + static inline JSTaggedValue FastStrictEqual(JSTaggedValue left, JSTaggedValue right); static inline JSTaggedValue NewLexicalEnv(JSThread *thread, ObjectFactory *factory, uint16_t numVars); static inline JSTaggedValue GetGlobalOwnProperty(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key); template diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index af459dc1d6..50adff140b 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -2050,8 +2050,17 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t << " v" << v0; JSTaggedValue left = GET_VREG_VALUE(v0); JSTaggedValue right = GET_ACC(); - bool res = FastRuntimeStub::FastStrictEqual(left, right); - SET_ACC(JSTaggedValue(!res)); + JSTaggedValue res = FastRuntimeStub::FastStrictEqual(left, right); + if (!res.IsHole()) { + res = res.IsTrue() ? JSTaggedValue::False() : JSTaggedValue::True(); + SET_ACC(res); + } else { + // slow path + SAVE_PC(); + res = SlowRuntimeStub::NotEq(thread, left, right); + INTERPRETER_RETURN_IF_ABRUPT(res); + SET_ACC(res); + } DISPATCH(STRICTNOTEQ_IMM8_V8); } HANDLE_OPCODE(STRICTEQ_IMM8_V8) { @@ -2060,8 +2069,16 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t << " v" << v0; JSTaggedValue left = GET_VREG_VALUE(v0); JSTaggedValue right = GET_ACC(); - bool res = FastRuntimeStub::FastStrictEqual(left, right); - SET_ACC(JSTaggedValue(res)); + JSTaggedValue res = FastRuntimeStub::FastStrictEqual(left, right); + if (!res.IsHole()) { + SET_ACC(res); + } else { + // slow path + SAVE_PC(); + res = SlowRuntimeStub::Eq(thread, left, right); + INTERPRETER_RETURN_IF_ABRUPT(res); + SET_ACC(res); + } DISPATCH(STRICTEQ_IMM8_V8); } HANDLE_OPCODE(CREATEITERRESULTOBJ_V8_V8) { diff --git a/ecmascript/interpreter/interpreter_assembly.cpp b/ecmascript/interpreter/interpreter_assembly.cpp index 37ecee4f41..29d50934f7 100644 --- a/ecmascript/interpreter/interpreter_assembly.cpp +++ b/ecmascript/interpreter/interpreter_assembly.cpp @@ -1540,8 +1540,16 @@ void InterpreterAssembly::HandleStrictnoteqImm8V8( << " v" << v0; JSTaggedValue left = GET_VREG_VALUE(v0); JSTaggedValue right = GET_ACC(); - bool res = FastRuntimeStub::FastStrictEqual(left, right); - SET_ACC(JSTaggedValue(!res)); + JSTaggedValue res = FastRuntimeStub::FastStrictEqual(left, right); + if (!res.IsHole()) { + res = res.IsTrue() ? JSTaggedValue::False() : JSTaggedValue::True(); + SET_ACC(res); + } else { + // slow path + res = SlowRuntimeStub::NotEq(thread, left, right); + INTERPRETER_RETURN_IF_ABRUPT(res); + SET_ACC(res); + } DISPATCH(STRICTNOTEQ_IMM8_V8); } @@ -1554,8 +1562,15 @@ void InterpreterAssembly::HandleStricteqImm8V8( << " v" << v0; JSTaggedValue left = GET_VREG_VALUE(v0); JSTaggedValue right = GET_ACC(); - bool res = FastRuntimeStub::FastStrictEqual(left, right); - SET_ACC(JSTaggedValue(res)); + JSTaggedValue res = FastRuntimeStub::FastStrictEqual(left, right); + if (!res.IsHole()) { + SET_ACC(res); + } else { + // slow path + res = SlowRuntimeStub::Eq(thread, left, right); + INTERPRETER_RETURN_IF_ABRUPT(res); + SET_ACC(res); + } DISPATCH(STRICTEQ_IMM8_V8); } diff --git a/ecmascript/js_hclass-inl.h b/ecmascript/js_hclass-inl.h index 673aea7fac..8e61bb8585 100644 --- a/ecmascript/js_hclass-inl.h +++ b/ecmascript/js_hclass-inl.h @@ -162,7 +162,7 @@ inline bool JSHClass::HasReferenceField() { auto type = GetObjectType(); switch (type) { - case JSType::STRING: + case JSType::LINE_STRING: case JSType::JS_NATIVE_POINTER: return false; default: @@ -189,7 +189,8 @@ inline size_t JSHClass::SizeFromJSHClass(TaggedObject *header) ByteArray::Cast(header)->GetLength()); size = AlignUp(size, static_cast(MemAlignment::MEM_ALIGN_OBJECT)); break; - case JSType::STRING: + case JSType::LINE_STRING: + case JSType::TREE_STRING: size = EcmaStringAccessor(reinterpret_cast(header)).ObjectSize(); size = AlignUp(size, static_cast(MemAlignment::MEM_ALIGN_OBJECT)); break; diff --git a/ecmascript/js_hclass.h b/ecmascript/js_hclass.h index c0018b7597..7d0678a8a6 100644 --- a/ecmascript/js_hclass.h +++ b/ecmascript/js_hclass.h @@ -180,7 +180,8 @@ class ProtoChangeDetails; JS_PROXY, /* ECMA_OBJECT_LAST ////////////////////////////////////////////////////////////////////////////// */\ \ HCLASS, /* //////////////////////////////////////////////////////////////////////////////////-PADDING */ \ - STRING, /* //////////////////////////////////////////////////////////////////////////////////-PADDING */ \ + LINE_STRING, /* //////////////////////////////////////////////////////////////////////////////////-PADDING */\ + TREE_STRING, /* //////////////////////////////////////////////////////////////////////////////////-PADDING */ \ BIGINT, /* //////////////////////////////////////////////////////////////////////////////////-PADDING */ \ TAGGED_ARRAY, /* //////////////////////////////////////////////////////////////////////////////////-PADDING */ \ BYTE_ARRAY, /* //////////////////////////////////////////////////////////////////////////////////-PADDING */ \ @@ -265,8 +266,10 @@ class ProtoChangeDetails; MODULE_RECORD_LAST = SOURCE_TEXT_MODULE_RECORD, /* ////////////////////////////////////////////////-PADDING */ \ \ TS_TYPE_FIRST = TS_ARRAY_TYPE, /* /////////////////////////////////////////////////////////////////-PADDING */ \ - TS_TYPE_LAST = TS_ITERATOR_INSTANCE_TYPE /* ///////////////////////////////////////////////////////-PADDING */ - + TS_TYPE_LAST = TS_ITERATOR_INSTANCE_TYPE, /* ///////////////////////////////////////////////////////-PADDING */\ + \ + STRING_FIRST = LINE_STRING, /* /////////////////////////////////////////////////////////////////////-PADDING */\ + STRING_LAST = TREE_STRING /* /////////////////////////////////////////////////////////////////////-PADDING */ enum class JSType : uint8_t { JSTYPE_DECL, @@ -446,7 +449,18 @@ public: inline bool IsString() const { - return GetObjectType() == JSType::STRING; + JSType jsType = GetObjectType(); + return (JSType::STRING_FIRST <= jsType && jsType <= JSType::STRING_LAST); + } + + inline bool IsLineString() const + { + return GetObjectType() == JSType::LINE_STRING; + } + + inline bool IsTreeString() const + { + return GetObjectType() == JSType::TREE_STRING; } inline bool IsBigInt() const @@ -462,7 +476,7 @@ public: inline bool IsStringOrSymbol() const { JSType jsType = GetObjectType(); - return (jsType == JSType::STRING) || (jsType == JSType::SYMBOL); + return (JSType::STRING_FIRST <= jsType && jsType <= JSType::STRING_LAST) || (jsType == JSType::SYMBOL); } inline bool IsTaggedArray() const diff --git a/ecmascript/js_locale.cpp b/ecmascript/js_locale.cpp index 6892891caa..fc786158fe 100644 --- a/ecmascript/js_locale.cpp +++ b/ecmascript/js_locale.cpp @@ -471,7 +471,7 @@ JSHandle JSLocale::BestFitSupportedLocales(JSThread *thread, const JSMutableHandle locale(thread, JSTaggedValue::Undefined()); for (uint32_t i = 0; i < requestLength; ++i) { locale.Update(requestedLocales->Get(thread, i)); - if (EcmaStringAccessor::StringsAreEqual(*locale, *defaultLocale)) { + if (EcmaStringAccessor::StringsAreEqual(thread->GetEcmaVM(), locale, defaultLocale)) { result->Set(thread, index++, locale.GetTaggedValue()); } else { status = U_ZERO_ERROR; @@ -479,7 +479,7 @@ JSHandle JSLocale::BestFitSupportedLocales(JSThread *thread, const icu::Locale desired = icu::Locale::forLanguageTag(localeStr, status); auto bestFit = matcher.getBestMatch(desired, status)->toLanguageTag(status); if ((U_SUCCESS(status) != 0) && - EcmaStringAccessor::StringsAreEqual(*locale, *(factory->NewFromStdString(bestFit)))) { + EcmaStringAccessor::StringsAreEqual(thread->GetEcmaVM(), locale, factory->NewFromStdString(bestFit))) { result->Set(thread, index++, locale.GetTaggedValue()); } } diff --git a/ecmascript/js_primitive_ref.cpp b/ecmascript/js_primitive_ref.cpp index 6e47120f13..0a7f6172f0 100644 --- a/ecmascript/js_primitive_ref.cpp +++ b/ecmascript/js_primitive_ref.cpp @@ -51,14 +51,16 @@ bool JSPrimitiveRef::StringGetIndexProperty(const JSThread *thread, const JSHand { uint16_t tmpChar; { - DISALLOW_GARBAGE_COLLECTION; - EcmaString *str = EcmaString::Cast(JSPrimitiveRef::Cast(*obj)->GetValue().GetTaggedObject()); - if (EcmaStringAccessor(str).GetLength() <= index) { + JSHandle strHandle = JSHandle(thread, + EcmaString::Cast(JSPrimitiveRef::Cast(*obj)->GetValue())); + JSHandle strFlat = JSHandle(thread, + EcmaStringAccessor::Flatten(thread->GetEcmaVM(), strHandle)); + if (EcmaStringAccessor(strFlat).GetLength() <= index) { return false; } // 10. Let resultStr be a String value of length 1, containing one code unit from str, specifically the code // unit at index index - tmpChar = EcmaStringAccessor(str).Get(index);; + tmpChar = EcmaStringAccessor(strFlat).Get(index); } JSHandle value(thread->GetEcmaVM()->GetFactory()->NewFromUtf16(&tmpChar, 1)); // 11. Return a PropertyDescriptor{ [[Value]]: resultStr, [[Enumerable]]: true, [[Writable]]: false, diff --git a/ecmascript/js_serializer.cpp b/ecmascript/js_serializer.cpp index 6c2a92a22f..31b29b5f34 100644 --- a/ecmascript/js_serializer.cpp +++ b/ecmascript/js_serializer.cpp @@ -300,7 +300,8 @@ bool JSSerializer::WriteTaggedObject(const JSHandle &value) case JSType::JS_ARRAY_BUFFER: case JSType::JS_SHARED_ARRAY_BUFFER: return WriteJSArrayBuffer(value); - case JSType::STRING: + case JSType::LINE_STRING: + case JSType::TREE_STRING: return WriteEcmaString(value); case JSType::JS_OBJECT: return WritePlainObject(value); @@ -504,7 +505,8 @@ bool JSSerializer::WriteJSArray(const JSHandle &value) bool JSSerializer::WriteEcmaString(const JSHandle &value) { - JSHandle string = JSHandle::Cast(value); + JSHandle strHandle = JSHandle::Cast(value); + auto string = JSHandle(thread_, EcmaStringAccessor::Flatten(thread_->GetEcmaVM(), strHandle)); size_t oldSize = bufferSize_; if (!WriteType(SerializationUID::ECMASTRING)) { return false; diff --git a/ecmascript/js_stable_array.cpp b/ecmascript/js_stable_array.cpp index 9b6b0e392c..4e070df13c 100644 --- a/ecmascript/js_stable_array.cpp +++ b/ecmascript/js_stable_array.cpp @@ -255,7 +255,7 @@ JSTaggedValue JSStableArray::Join(JSHandle receiver, EcmaRuntimeCallInf if (len > 0) { allocateLength += sepLength * (len - 1); } - auto newString = EcmaStringAccessor::AllocStringObject(thread->GetEcmaVM(), allocateLength, isOneByte); + auto newString = EcmaStringAccessor::CreateLineString(thread->GetEcmaVM(), allocateLength, isOneByte); int current = 0; DISALLOW_GARBAGE_COLLECTION; for (uint32_t k = 0; k < len; k++) { diff --git a/ecmascript/js_tagged_value-inl.h b/ecmascript/js_tagged_value-inl.h index fde5ba8ed6..406ca59dd8 100644 --- a/ecmascript/js_tagged_value-inl.h +++ b/ecmascript/js_tagged_value-inl.h @@ -462,6 +462,16 @@ inline bool JSTaggedValue::IsString() const return IsHeapObject() && GetTaggedObject()->GetClass()->IsString(); } +inline bool JSTaggedValue::IsLineString() const +{ + return IsHeapObject() && GetTaggedObject()->GetClass()->IsLineString(); +} + +inline bool JSTaggedValue::IsTreeString() const +{ + return IsHeapObject() && GetTaggedObject()->GetClass()->IsTreeString(); +} + inline bool JSTaggedValue::IsBigInt() const { return IsHeapObject() && GetTaggedObject()->GetClass()->IsBigInt(); @@ -1396,7 +1406,7 @@ inline JSTaggedNumber JSTaggedValue::StringToDouble(JSTaggedValue tagged) if (strLen == 0) { return JSTaggedNumber(0); } - [[maybe_unused]] CVector buf; + CVector buf; Span str = EcmaStringAccessor(strObj).ToUtf8Span(buf); double d = base::NumberHelper::StringToDouble(str.begin(), str.end(), 0, base::ALLOW_BINARY + base::ALLOW_OCTAL + base::ALLOW_HEX); diff --git a/ecmascript/js_tagged_value.cpp b/ecmascript/js_tagged_value.cpp index 55d3ab90e0..ae8e94a95b 100644 --- a/ecmascript/js_tagged_value.cpp +++ b/ecmascript/js_tagged_value.cpp @@ -155,8 +155,9 @@ bool JSTaggedValue::Equal(JSThread *thread, const JSHandle &x, co if (x->IsString()) { if (y->IsString()) { - return EcmaStringAccessor::StringsAreEqual(static_cast(x->GetTaggedObject()), - static_cast(y->GetTaggedObject())); + return EcmaStringAccessor::StringsAreEqual(thread->GetEcmaVM(), + JSHandle(x), + JSHandle(y)); } if (y->IsNumber()) { JSTaggedNumber xNumber = ToNumber(thread, x); @@ -274,9 +275,9 @@ ComparisonResult JSTaggedValue::Compare(JSThread *thread, const JSHandle primY(thread, ToPrimitive(thread, y)); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); if (primX->IsString() && primY->IsString()) { - auto xString = static_cast(primX->GetTaggedObject()); - auto yString = static_cast(primY->GetTaggedObject()); - int result = EcmaStringAccessor::Compare(xString, yString); + auto xHandle = JSHandle(primX); + auto yHandle = JSHandle(primY); + int result = EcmaStringAccessor::Compare(thread->GetEcmaVM(), xHandle, yHandle); if (result < 0) { return ComparisonResult::LESS; } @@ -455,7 +456,7 @@ JSTaggedValue JSTaggedValue::CanonicalNumericIndexString(JSThread *thread, const if (tagged->IsString()) { JSHandle str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("-0"); - if (EcmaStringAccessor::StringsAreEqual(static_cast(tagged->GetTaggedObject()), *str)) { + if (EcmaStringAccessor::StringsAreEqual(thread->GetEcmaVM(), JSHandle(tagged), str)) { return JSTaggedValue(-0.0); } JSHandle tmp(thread, ToNumber(thread, tagged)); diff --git a/ecmascript/js_tagged_value.h b/ecmascript/js_tagged_value.h index 193eabd56f..38e73b596c 100644 --- a/ecmascript/js_tagged_value.h +++ b/ecmascript/js_tagged_value.h @@ -495,6 +495,8 @@ public: bool IsNumber() const; bool IsBigInt() const; bool IsString() const; + bool IsLineString() const; + bool IsTreeString() const; bool IsStringOrSymbol() const; bool IsTaggedArray() const; bool IsByteArray() const; diff --git a/ecmascript/mem/object_xray.h b/ecmascript/mem/object_xray.h index aee0c12dc8..e46c321c64 100644 --- a/ecmascript/mem/object_xray.h +++ b/ecmascript/mem/object_xray.h @@ -322,7 +322,10 @@ public: JSHClass::Cast(object)->VisitRangeSlot(visitor); } break; - case JSType::STRING: + case JSType::LINE_STRING: + break; + case JSType::TREE_STRING: + TreeEcmaString::Cast(object)->VisitRangeSlot(visitor); break; case JSType::JS_NATIVE_POINTER: if (visitType == VisitType::SNAPSHOT_VISIT) { diff --git a/ecmascript/napi/include/jsnapi.h b/ecmascript/napi/include/jsnapi.h index 08dd9f6ed8..ecf20dc2b3 100644 --- a/ecmascript/napi/include/jsnapi.h +++ b/ecmascript/napi/include/jsnapi.h @@ -527,7 +527,7 @@ public: static Local NewFromUtf8(const EcmaVM *vm, const char *utf8, int length = -1); std::string ToString(); int32_t Length(); - int32_t Utf8Length(); + int32_t Utf8Length(const EcmaVM *vm); int WriteUtf8(char *buffer, int length, bool isWriteBuffer = false); }; diff --git a/ecmascript/napi/jsnapi.cpp b/ecmascript/napi/jsnapi.cpp index feda3db80c..2550cfe371 100644 --- a/ecmascript/napi/jsnapi.cpp +++ b/ecmascript/napi/jsnapi.cpp @@ -917,9 +917,10 @@ int32_t StringRef::Length() return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this)).GetLength(); } -int32_t StringRef::Utf8Length() +int32_t StringRef::Utf8Length(const EcmaVM *vm) { - return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this)).GetUtf8Length(); + JSHandle strHandle(vm->GetJSThread(), EcmaString::Cast(JSNApiHelper::ToJSTaggedValue(this))); + return EcmaStringAccessor(EcmaStringAccessor::Flatten(vm, strHandle)).GetUtf8Length(); } int StringRef::WriteUtf8(char *buffer, int length, bool isWriteBuffer) diff --git a/ecmascript/napi/test/jsnapi_tests.cpp b/ecmascript/napi/test/jsnapi_tests.cpp index eeb118cbbb..f807c65d05 100644 --- a/ecmascript/napi/test/jsnapi_tests.cpp +++ b/ecmascript/napi/test/jsnapi_tests.cpp @@ -215,7 +215,7 @@ HWTEST_F_L0(JSNApiTests, StringUtf8_001) std::string test = "Hello world"; Local testString = StringRef::NewFromUtf8(vm_, test.c_str()); - EXPECT_EQ(testString->Utf8Length(), 12); // 12 : length of testString("Hello World") + EXPECT_EQ(testString->Utf8Length(vm_), 12); // 12 : length of testString("Hello World") char buffer[12]; // 12 : length of testString EXPECT_EQ(testString->WriteUtf8(buffer, 12), 12); // 12 : length of testString("Hello World") std::string res(buffer); @@ -228,7 +228,7 @@ HWTEST_F_L0(JSNApiTests, StringUtf8_002) std::string test = "年"; Local testString = StringRef::NewFromUtf8(vm_, test.c_str()); - EXPECT_EQ(testString->Utf8Length(), 4); // 4 : length of testString("年") + EXPECT_EQ(testString->Utf8Length(vm_), 4); // 4 : length of testString("年") char buffer[4]; // 4 : length of testString EXPECT_EQ(testString->WriteUtf8(buffer, 4), 4); // 4 : length of testString("年") std::string res(buffer); @@ -244,7 +244,7 @@ HWTEST_F_L0(JSNApiTests, StringUtf8_003) // isWriteBuffer == false, \u0000 ==> C080 Local testString1 = StringRef::NewFromUtf8(vm_, test.c_str(), test.length()); - EXPECT_EQ(testString1->Utf8Length(), 5); + EXPECT_EQ(testString1->Utf8Length(vm_), 5); char buffer1[4]; testString1->WriteUtf8(buffer1, 4, false); EXPECT_EQ(buffer1[0], 'a'); @@ -254,7 +254,7 @@ HWTEST_F_L0(JSNApiTests, StringUtf8_003) // isWriteBuffer == true, \u0000 ==> 0x00U Local testString2 = StringRef::NewFromUtf8(vm_, test.c_str(), test.length()); - EXPECT_EQ(testString2->Utf8Length(), 5); + EXPECT_EQ(testString2->Utf8Length(vm_), 5); char buffer2[4]; testString2->WriteUtf8(buffer2, 4, true); EXPECT_EQ(buffer2[0], 'a'); diff --git a/ecmascript/object_factory-inl.h b/ecmascript/object_factory-inl.h index efc2e292be..24441e534c 100644 --- a/ecmascript/object_factory-inl.h +++ b/ecmascript/object_factory-inl.h @@ -26,25 +26,32 @@ #include "ecmascript/tagged_array-inl.h" namespace panda::ecmascript { -EcmaString *ObjectFactory::AllocNonMovableStringObject(size_t size) +EcmaString *ObjectFactory::AllocNonMovableLineStringObject(size_t size) { NewObjectHook(); return reinterpret_cast(heap_->AllocateNonMovableOrHugeObject( - JSHClass::Cast(thread_->GlobalConstants()->GetStringClass().GetTaggedObject()), size)); + JSHClass::Cast(thread_->GlobalConstants()->GetLineStringClass().GetTaggedObject()), size)); } -EcmaString *ObjectFactory::AllocStringObject(size_t size) +EcmaString *ObjectFactory::AllocLineStringObject(size_t size) { NewObjectHook(); return reinterpret_cast(heap_->AllocateYoungOrHugeObject( - JSHClass::Cast(thread_->GlobalConstants()->GetStringClass().GetTaggedObject()), size)); + JSHClass::Cast(thread_->GlobalConstants()->GetLineStringClass().GetTaggedObject()), size)); } -EcmaString *ObjectFactory::AllocOldSpaceStringObject(size_t size) +EcmaString *ObjectFactory::AllocOldSpaceLineStringObject(size_t size) { NewObjectHook(); return reinterpret_cast(heap_->AllocateOldOrHugeObject( - JSHClass::Cast(thread_->GlobalConstants()->GetStringClass().GetTaggedObject()), size)); + JSHClass::Cast(thread_->GlobalConstants()->GetLineStringClass().GetTaggedObject()), size)); +} + +EcmaString *ObjectFactory::AllocTreeStringObject() +{ + NewObjectHook(); + return reinterpret_cast(heap_->AllocateYoungOrHugeObject( + JSHClass::Cast(thread_->GlobalConstants()->GetTreeStringClass().GetTaggedObject()), TreeEcmaString::SIZE)); } JSHandle ObjectFactory::NewJSNativePointer(void *externalPointer, diff --git a/ecmascript/object_factory.h b/ecmascript/object_factory.h index ea557177ca..f7ba219041 100644 --- a/ecmascript/object_factory.h +++ b/ecmascript/object_factory.h @@ -503,6 +503,11 @@ public: JSHandle NewFromUtf16LiteralCompress(const uint16_t *utf16Data, uint32_t utf16Len); JSHandle NewFromUtf16LiteralNotCompress(const uint16_t *utf16Data, uint32_t utf16Len); + inline EcmaString *AllocLineStringObject(size_t size); + inline EcmaString *AllocOldSpaceLineStringObject(size_t size); + inline EcmaString *AllocNonMovableLineStringObject(size_t size); + inline EcmaString *AllocTreeStringObject(); + JSHandle ConcatFromString(const JSHandle &firstString, const JSHandle &secondString); @@ -656,9 +661,6 @@ private: JSHandle GetStringFromStringTable(const JSHandle &firstString, const JSHandle &secondString); - inline EcmaString *AllocStringObject(size_t size); - inline EcmaString *AllocOldSpaceStringObject(size_t size); - inline EcmaString *AllocNonMovableStringObject(size_t size); JSHandle NewEmptyArray(); // only used for EcmaVM. JSHandle CreateJSArguments(); diff --git a/ecmascript/regexp/tests/regexp_test.cpp b/ecmascript/regexp/tests/regexp_test.cpp index 8a1b4a40ee..3b74043ff5 100644 --- a/ecmascript/regexp/tests/regexp_test.cpp +++ b/ecmascript/regexp/tests/regexp_test.cpp @@ -643,7 +643,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec1) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("ab"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec2) @@ -665,10 +665,10 @@ HWTEST_F_L0(RegExpTest, ParseAndExec2) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 10U); JSHandle str = factory->NewFromASCII("ab"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[1].second, *str) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[2].second, *str) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[3].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[1].second, str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[2].second, str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[3].second, str) == 0); ASSERT_TRUE(result.captures_[4].first); ASSERT_TRUE(result.captures_[5].first); ASSERT_TRUE(result.captures_[6].first); @@ -697,8 +697,8 @@ HWTEST_F_L0(RegExpTest, ParseAndExec3) ASSERT_EQ(result.captures_.size(), 2U); JSHandle str1 = factory->NewFromASCII("aaba"); JSHandle str2 = factory->NewFromASCII("ba"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str1) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[1].second, *str2) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str1) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[1].second, str2) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec4) @@ -720,7 +720,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec4) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("aa"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec5) @@ -742,7 +742,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec5) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII(""); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec6) @@ -768,12 +768,12 @@ HWTEST_F_L0(RegExpTest, ParseAndExec6) JSHandle str3 = factory->NewFromASCII("ac"); JSHandle str4 = factory->NewFromASCII("a"); JSHandle str5 = factory->NewFromASCII("c"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str1) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[1].second, *str2) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[2].second, *str3) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[3].second, *str4) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str1) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[1].second, str2) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[2].second, str3) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[3].second, str4) == 0); ASSERT_TRUE(result.captures_[4].first); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[5].second, *str5) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[5].second, str5) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec7) @@ -795,7 +795,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec7) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("abc"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec8) @@ -817,7 +817,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec8) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("abc"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec9) @@ -839,7 +839,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec9) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("er"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec10) @@ -861,7 +861,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec10) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("d"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec11) @@ -883,7 +883,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec11) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("a"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec12) @@ -905,7 +905,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec12) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("\n"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec13) @@ -927,7 +927,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec13) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("abc"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec14) @@ -949,7 +949,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec14) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("abc"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec15) @@ -971,7 +971,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec15) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("a"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec16) @@ -993,7 +993,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec16) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("ABC"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec17) @@ -1015,7 +1015,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec17) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("a\n"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec18) @@ -1053,7 +1053,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec19) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("a"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec20) @@ -1076,8 +1076,8 @@ HWTEST_F_L0(RegExpTest, ParseAndExec20) ASSERT_EQ(result.captures_.size(), 2U); JSHandle str1 = factory->NewFromASCII(""); JSHandle str2 = factory->NewFromASCII("aaa"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str1) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[1].second, *str2) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str1) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[1].second, str2) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec21) @@ -1099,7 +1099,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec21) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("a"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec22) @@ -1121,7 +1121,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec22) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("aaaa:"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec23) @@ -1143,7 +1143,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec23) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("a"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec24) @@ -1182,8 +1182,8 @@ HWTEST_F_L0(RegExpTest, ParseAndExec25) ASSERT_EQ(result.captures_.size(), 2U); JSHandle str1 = factory->NewFromASCII(""); JSHandle str2 = factory->NewFromASCII("ab"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str1) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[1].second, *str2) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str1) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[1].second, str2) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec26) @@ -1205,7 +1205,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec26) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("A"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec27) @@ -1227,7 +1227,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec27) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("Z"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec28) @@ -1249,7 +1249,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec28) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("\n"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec29) @@ -1271,8 +1271,8 @@ HWTEST_F_L0(RegExpTest, ParseAndExec29) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 2U); JSHandle str = factory->NewFromASCII(""); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[1].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[1].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec30) @@ -1294,7 +1294,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec30) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 2U); JSHandle str = factory->NewFromASCII(""); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); ASSERT_TRUE(result.captures_[1].first); } @@ -1316,8 +1316,8 @@ HWTEST_F_L0(RegExpTest, ParseAndExec31) ASSERT_EQ(result.captures_.size(), 2U); JSHandle str1 = factory->NewFromASCII("abb"); JSHandle str2 = factory->NewFromASCII("b"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str1) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[1].second, *str2) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str1) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[1].second, str2) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec32) @@ -1339,9 +1339,9 @@ HWTEST_F_L0(RegExpTest, ParseAndExec32) JSHandle str1 = factory->NewFromASCII("abb"); JSHandle str2 = factory->NewFromASCII("ab"); JSHandle str3 = factory->NewFromASCII("b"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str1) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[1].second, *str2) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[2].second, *str3) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str1) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[1].second, str2) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[2].second, str3) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec33) @@ -1361,7 +1361,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec33) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("qya"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec34) @@ -1381,7 +1381,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec34) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("qy"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec35) @@ -1404,10 +1404,10 @@ HWTEST_F_L0(RegExpTest, ParseAndExec35) JSHandle str2 = factory->NewFromASCII("2021"); JSHandle str3 = factory->NewFromASCII("01"); JSHandle str4 = factory->NewFromASCII("09"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str1) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[1].second, *str2) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[2].second, *str3) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[3].second, *str4) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str1) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[1].second, str2) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[2].second, str3) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[3].second, str4) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec36) @@ -1429,9 +1429,9 @@ HWTEST_F_L0(RegExpTest, ParseAndExec36) JSHandle str1 = factory->NewFromASCII("Quick Brown Fox Jumps"); JSHandle str2 = factory->NewFromASCII("Brown"); JSHandle str3 = factory->NewFromASCII("Jumps"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str1) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[1].second, *str2) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[2].second, *str3) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str1) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[1].second, str2) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[2].second, str3) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec37) @@ -1452,8 +1452,8 @@ HWTEST_F_L0(RegExpTest, ParseAndExec37) ASSERT_EQ(result.captures_.size(), 2U); JSHandle str1 = factory->NewFromASCII("abABc"); JSHandle str2 = factory->NewFromASCII("AB"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str1) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[1].second, *str2) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str1) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[1].second, str2) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec38) @@ -1475,9 +1475,9 @@ HWTEST_F_L0(RegExpTest, ParseAndExec38) JSHandle str1 = factory->NewFromASCII("www.netscape.com"); JSHandle str2 = factory->NewFromASCII("netscape."); JSHandle str3 = factory->NewFromASCII("netscap"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str1) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[1].second, *str2) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[2].second, *str3) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str1) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[1].second, str2) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[2].second, str3) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec39) @@ -1498,8 +1498,8 @@ HWTEST_F_L0(RegExpTest, ParseAndExec39) ASSERT_EQ(result.captures_.size(), 2U); JSHandle str1 = factory->NewFromASCII("b"); JSHandle str2 = factory->NewFromASCII(""); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str1) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[1].second, *str2) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str1) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[1].second, str2) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec40) @@ -1519,7 +1519,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec40) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII(""); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec41) @@ -1541,10 +1541,10 @@ HWTEST_F_L0(RegExpTest, ParseAndExec41) JSHandle str1 = factory->NewFromASCII("baaabaac"); JSHandle str2 = factory->NewFromASCII("ba"); JSHandle str3 = factory->NewFromASCII("abaac"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str1) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[1].second, *str2) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str1) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[1].second, str2) == 0); ASSERT_TRUE(result.captures_[2].first); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[3].second, *str3) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[3].second, str3) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec42) @@ -1564,7 +1564,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec42) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("abc324234"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec43) @@ -1584,7 +1584,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec43) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("1\nl"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec44) @@ -1604,7 +1604,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec44) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("c\bd"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec45) @@ -1624,7 +1624,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec45) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("easy"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec46) @@ -1645,9 +1645,9 @@ HWTEST_F_L0(RegExpTest, ParseAndExec46) ASSERT_EQ(result.captures_.size(), 3U); JSHandle str1 = factory->NewFromASCII("Course_Creator = Test"); JSHandle str2 = factory->NewFromASCII("Course_Creator"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str1) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str1) == 0); ASSERT_FALSE(result.captures_[1].first); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[1].second, *str2) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[1].second, str2) == 0); ASSERT_TRUE(result.captures_[2].first); } @@ -1668,7 +1668,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec47) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("et"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec49) @@ -1692,11 +1692,11 @@ HWTEST_F_L0(RegExpTest, ParseAndExec49) JSHandle str3 = factory->NewFromASCII("b"); JSHandle str4 = factory->NewFromASCII("5"); JSHandle str5 = factory->NewFromASCII("5"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str1) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[1].second, *str2) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[2].second, *str3) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[3].second, *str4) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[4].second, *str5) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str1) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[1].second, str2) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[2].second, str3) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[3].second, str4) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[4].second, str5) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec50) @@ -1719,10 +1719,10 @@ HWTEST_F_L0(RegExpTest, ParseAndExec50) JSHandle str2 = factory->NewFromASCII("2020"); JSHandle str3 = factory->NewFromASCII("12-31"); JSHandle str4 = factory->NewFromASCII("31"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str1) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[1].second, *str2) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[2].second, *str3) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[3].second, *str4) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str1) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[1].second, str2) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[2].second, str3) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[3].second, str4) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec51) @@ -1760,8 +1760,8 @@ HWTEST_F_L0(RegExpTest, ParseAndExec52) ASSERT_EQ(result.captures_.size(), 2U); JSHandle str1 = factory->NewFromASCII("aabcdaa"); JSHandle str2 = factory->NewFromASCII("aa"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str1) == 0); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[1].second, *str2) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str1) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[1].second, str2) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec53) @@ -1781,7 +1781,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec53) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("\u0001"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec54) @@ -1816,7 +1816,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec55) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("e"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec56) @@ -1836,7 +1836,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec56) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromUtf8("a啊"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec57) @@ -1870,7 +1870,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec58) ASSERT_EQ(result.captures_.size(), 1U); char16_t data1[] = {0xdf06}; JSHandle str = factory->NewFromUtf16(reinterpret_cast(data1), 1); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, ParseAndExec59) @@ -1892,7 +1892,7 @@ HWTEST_F_L0(RegExpTest, ParseAndExec59) MatchResult result = executor.GetResult(thread, ret); ASSERT_EQ(result.captures_.size(), 1U); JSHandle str = factory->NewFromASCII("\u000B"); - ASSERT_TRUE(EcmaStringAccessor::Compare(*result.captures_[0].second, *str) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, result.captures_[0].second, str) == 0); } HWTEST_F_L0(RegExpTest, RangeSet1) diff --git a/ecmascript/snapshot/mem/snapshot_processor.cpp b/ecmascript/snapshot/mem/snapshot_processor.cpp index 28cd91a769..7c98f5302b 100644 --- a/ecmascript/snapshot/mem/snapshot_processor.cpp +++ b/ecmascript/snapshot/mem/snapshot_processor.cpp @@ -1316,9 +1316,10 @@ void SnapshotProcessor::DeserializeString(uintptr_t stringBegin, uintptr_t strin auto oldSpace = const_cast(vm_->GetHeap())->GetOldSpace(); auto hugeSpace = const_cast(vm_->GetHeap())->GetHugeObjectSpace(); auto globalConst = const_cast(vm_->GetJSThread()->GlobalConstants()); - auto stringClass = globalConst->GetStringClass(); + auto stringClass = globalConst->GetLineStringClass(); while (stringBegin < stringEnd) { EcmaString *str = reinterpret_cast(stringBegin); + str->SetClassWithoutBarrier(reinterpret_cast(stringClass.GetTaggedObject())); size_t strSize = EcmaStringAccessor(str).ObjectSize(); strSize = AlignUp(strSize, static_cast(MemAlignment::MEM_ALIGN_OBJECT)); auto strFromTable = stringTable->GetString(str); @@ -1340,7 +1341,6 @@ void SnapshotProcessor::DeserializeString(uintptr_t stringBegin, uintptr_t strin UNREACHABLE(); } str = reinterpret_cast(newObj); - str->SetClass(reinterpret_cast(stringClass.GetTaggedObject())); EcmaStringAccessor(str).ClearInternString(); stringTable->GetOrInternString(str); stringVector_.emplace_back(newObj); @@ -1496,7 +1496,8 @@ void SnapshotProcessor::RelocateSpaceObject(Space* space, SnapshotType type, Met TaggedObject *objectHeader = reinterpret_cast(begin); DeserializeClassWord(objectHeader); DeserializeField(objectHeader); - if (builtinsDeserialize_ && JSType(objType) == JSType::STRING) { + if (builtinsDeserialize_ && + (JSType(objType) >= JSType::STRING_FIRST && JSType(objType) <= JSType::STRING_LAST)) { auto str = reinterpret_cast(begin); EcmaStringAccessor(str).ClearInternString(); stringTable->InsertStringIfNotExist(str); @@ -1724,9 +1725,13 @@ EncodeBit SnapshotProcessor::EncodeTaggedObject(TaggedObject *objectHeader, CQue { if (!builtinsSerialize_) { // String duplicate - if (objectHeader->GetClass()->GetObjectType() == JSType::STRING) { + if (objectHeader->GetClass()->IsString()) { ASSERT(stringVector_.size() < Constants::MAX_OBJECT_INDEX); EncodeBit encodeBit(stringVector_.size()); + if (EcmaStringAccessor(objectHeader).IsTreeString()) { + data->emplace(ToUintPtr(objectHeader), std::make_pair(0U, encodeBit)); + objectHeader = EcmaStringAccessor::FlattenNoGC(vm_, EcmaString::Cast(objectHeader)); + } stringVector_.emplace_back(ToUintPtr(objectHeader)); data->emplace(ToUintPtr(objectHeader), std::make_pair(0U, encodeBit)); return encodeBit; @@ -1743,6 +1748,12 @@ EncodeBit SnapshotProcessor::EncodeTaggedObject(TaggedObject *objectHeader, CQue } } } + auto oldObjHeader = objectHeader; + if (objectHeader->GetClass()->IsString()) { + if (EcmaStringAccessor(objectHeader).IsTreeString()) { + objectHeader = EcmaStringAccessor::FlattenNoGC(vm_, EcmaString::Cast(objectHeader)); + } + } queue->emplace(objectHeader); size_t objectSize = objectHeader->GetClass()->SizeFromJSHClass(objectHeader); if (objectSize == 0) { @@ -1780,6 +1791,11 @@ EncodeBit SnapshotProcessor::EncodeTaggedObject(TaggedObject *objectHeader, CQue size_t objOffset = newObj - ToUintPtr(currentRegion); EncodeBit encodeBit(static_cast(regionIndex)); encodeBit.SetObjectOffsetInRegion(objOffset); + if (oldObjHeader->GetClass()->IsString()) { + if (EcmaStringAccessor(oldObjHeader).IsTreeString()) { + data->emplace(ToUintPtr(oldObjHeader), std::make_pair(0U, encodeBit)); + } + } data->emplace(ToUintPtr(objectHeader), std::make_pair(newObj, encodeBit)); return encodeBit; } diff --git a/ecmascript/snapshot/tests/snapshot_test.cpp b/ecmascript/snapshot/tests/snapshot_test.cpp index ca9e6c7404..3b8b4a766b 100644 --- a/ecmascript/snapshot/tests/snapshot_test.cpp +++ b/ecmascript/snapshot/tests/snapshot_test.cpp @@ -69,18 +69,25 @@ HWTEST_F_L0(SnapshotTest, SerializeConstPool) auto factory = ecmaVm->GetFactory(); auto env = ecmaVm->GetGlobalEnv(); - JSHandle constpool = factory->NewConstantPool(6); + JSHandle constpool = factory->NewConstantPool(10); JSHandle funcFunc(env->GetFunctionFunction()); JSHandle dateFunc(env->GetDateFunction()); JSHandle numberFunc(env->GetNumberFunction()); JSHandle str1 = factory->NewFromASCII("str11"); JSHandle str2 = factory->NewFromASCII("str22"); + JSHandle str3 = factory->NewFromASCII("str333333333333"); + JSHandle str4 = factory->ConcatFromString(str1, str3); + JSHandle str5 = factory->NewFromASCII("str44"); constpool->SetObjectToCache(thread, 0, funcFunc.GetTaggedValue()); constpool->SetObjectToCache(thread, 1, dateFunc.GetTaggedValue()); constpool->SetObjectToCache(thread, 2, str1.GetTaggedValue()); constpool->SetObjectToCache(thread, 3, numberFunc.GetTaggedValue()); constpool->SetObjectToCache(thread, 4, str2.GetTaggedValue()); constpool->SetObjectToCache(thread, 5, str1.GetTaggedValue()); + constpool->SetObjectToCache(thread, 6, str3.GetTaggedValue()); + constpool->SetObjectToCache(thread, 7, str4.GetTaggedValue()); + constpool->SetObjectToCache(thread, 8, str4.GetTaggedValue()); + constpool->SetObjectToCache(thread, 9, str5.GetTaggedValue()); CString fileName = "snapshot"; Snapshot snapshotSerialize(ecmaVm); @@ -100,9 +107,17 @@ HWTEST_F_L0(SnapshotTest, SerializeConstPool) EcmaString *str11 = reinterpret_cast(constpool1->Get(2).GetTaggedObject()); EcmaString *str22 = reinterpret_cast(constpool1->Get(4).GetTaggedObject()); EcmaString *str33 = reinterpret_cast(constpool1->Get(5).GetTaggedObject()); + EcmaString *str44 = reinterpret_cast(constpool1->Get(6).GetTaggedObject()); + EcmaString *str55 = reinterpret_cast(constpool1->Get(7).GetTaggedObject()); + EcmaString *str66 = reinterpret_cast(constpool1->Get(8).GetTaggedObject()); + EcmaString *str77 = reinterpret_cast(constpool1->Get(9).GetTaggedObject()); EXPECT_EQ(std::strcmp(EcmaStringAccessor(str11).ToCString().c_str(), "str11"), 0); EXPECT_EQ(std::strcmp(EcmaStringAccessor(str22).ToCString().c_str(), "str22"), 0); EXPECT_EQ(std::strcmp(EcmaStringAccessor(str33).ToCString().c_str(), "str11"), 0); + EXPECT_EQ(std::strcmp(EcmaStringAccessor(str44).ToCString().c_str(), "str333333333333"), 0); + EXPECT_EQ(std::strcmp(EcmaStringAccessor(str55).ToCString().c_str(), "str11str333333333333"), 0); + EXPECT_EQ(std::strcmp(EcmaStringAccessor(str66).ToCString().c_str(), "str11str333333333333"), 0); + EXPECT_EQ(std::strcmp(EcmaStringAccessor(str77).ToCString().c_str(), "str44"), 0); std::remove(fileName.c_str()); } diff --git a/ecmascript/stubs/runtime_stubs-inl.h b/ecmascript/stubs/runtime_stubs-inl.h index 9c4077abdb..17b2032d28 100644 --- a/ecmascript/stubs/runtime_stubs-inl.h +++ b/ecmascript/stubs/runtime_stubs-inl.h @@ -367,10 +367,12 @@ JSTaggedValue RuntimeStubs::RuntimeStArraySpread(JSThread *thread, const JSHandl if (src->IsString()) { JSHandle srcString = JSTaggedValue::ToString(thread, src); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + JSHandle srcFlat = JSHandle(thread, + EcmaStringAccessor::Flatten(thread->GetEcmaVM(), srcString)); uint32_t dstLen = static_cast(index.GetInt()); - uint32_t strLen = EcmaStringAccessor(srcString).GetLength(); + uint32_t strLen = EcmaStringAccessor(srcFlat).GetLength(); for (uint32_t i = 0; i < strLen; i++) { - uint16_t res = EcmaStringAccessor(srcString).Get(i); + uint16_t res = EcmaStringAccessor(srcFlat).Get(i); JSHandle strValue(factory->NewFromUtf16Literal(&res, 1)); JSTaggedValue::SetProperty(thread, dst, dstLen + i, strValue, true); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); @@ -1345,10 +1347,8 @@ JSTaggedValue RuntimeStubs::RuntimeAdd2(JSThread *thread, const JSHandle &right) { if (left->IsString() && right->IsString()) { - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - JSHandle newString = - factory->ConcatFromString(JSHandle(left), JSHandle(right)); - return newString.GetTaggedValue(); + return JSTaggedValue(EcmaStringAccessor::Concat( + thread->GetEcmaVM(), JSHandle(left), JSHandle(right))); } JSHandle primitiveA0(thread, JSTaggedValue::ToPrimitive(thread, left)); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); @@ -1360,9 +1360,7 @@ JSTaggedValue RuntimeStubs::RuntimeAdd2(JSThread *thread, const JSHandle stringA1 = JSTaggedValue::ToString(thread, primitiveA1); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - JSHandle newString = factory->ConcatFromString(stringA0, stringA1); - return newString.GetTaggedValue(); + return JSTaggedValue(EcmaStringAccessor::Concat(thread->GetEcmaVM(), stringA0, stringA1)); } JSHandle valLeft = JSTaggedValue::ToNumeric(thread, primitiveA0); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); diff --git a/ecmascript/stubs/runtime_stubs.cpp b/ecmascript/stubs/runtime_stubs.cpp index 58fdbce123..1e63dea28b 100644 --- a/ecmascript/stubs/runtime_stubs.cpp +++ b/ecmascript/stubs/runtime_stubs.cpp @@ -1836,11 +1836,12 @@ DEF_RUNTIME_STUBS(BigIntEqual) DEF_RUNTIME_STUBS(StringEqual) { RUNTIME_STUBS_HEADER(StringEqual); - JSTaggedValue left = GetArg(argv, argc, 0); // 0: means the zeroth parameter - JSTaggedValue right = GetArg(argv, argc, 1); // 1: means the first parameter - auto leftStr = EcmaString::Cast(left.GetTaggedObject()); - auto rightStr = EcmaString::Cast(right.GetTaggedObject()); - if (EcmaStringAccessor::StringsAreEqualSameUtfEncoding(leftStr, rightStr)) { + JSHandle left = GetHArg(argv, argc, 0); + JSHandle right = GetHArg(argv, argc, 1); + EcmaVM *vm = thread->GetEcmaVM(); + left = JSHandle(thread, EcmaStringAccessor::Flatten(vm, left)); + right = JSHandle(thread, EcmaStringAccessor::Flatten(vm, right)); + if (EcmaStringAccessor::StringsAreEqualSameUtfEncoding(*left, *right)) { return JSTaggedValue::VALUE_TRUE; } return JSTaggedValue::VALUE_FALSE; @@ -1899,6 +1900,13 @@ DEF_RUNTIME_STUBS(ContainerRBTreeForEach) return JSTaggedValue::True().GetRawData(); } +DEF_RUNTIME_STUBS(SlowFlattenString) +{ + RUNTIME_STUBS_HEADER(SlowFlattenString); + JSHandle str = GetHArg(argv, argc, 0); // 0: means the zeroth parameter + return JSTaggedValue(EcmaStringAccessor::SlowFlatten(thread->GetEcmaVM(), str)).GetRawData(); +} + JSTaggedType RuntimeStubs::CreateArrayFromList([[maybe_unused]]uintptr_t argGlue, int32_t argc, JSTaggedValue *argvPtr) { auto thread = JSThread::GlueToJSThread(argGlue); diff --git a/ecmascript/stubs/runtime_stubs.h b/ecmascript/stubs/runtime_stubs.h index ce05d7bddc..adfd394b5b 100644 --- a/ecmascript/stubs/runtime_stubs.h +++ b/ecmascript/stubs/runtime_stubs.h @@ -276,7 +276,8 @@ using JSFunctionEntryType = JSTaggedValue (*)(uintptr_t glue, uint32_t argc, con V(LdPatchVar) \ V(StPatchVar) \ V(DeoptHandler) \ - V(ContainerRBTreeForEach) + V(ContainerRBTreeForEach) \ + V(SlowFlattenString) #define RUNTIME_STUB_LIST(V) \ RUNTIME_ASM_STUB_LIST(V) \ diff --git a/ecmascript/tagged_tree.h b/ecmascript/tagged_tree.h index 7a446a2c8c..b53ab859f0 100644 --- a/ecmascript/tagged_tree.h +++ b/ecmascript/tagged_tree.h @@ -377,9 +377,9 @@ protected: const JSHandle valueY) { if (valueX->IsString() && valueY->IsString()) { - auto xString = static_cast(valueX->GetTaggedObject()); - auto yString = static_cast(valueY->GetTaggedObject()); - int result = EcmaStringAccessor::Compare(xString, yString); + auto xHandle = JSHandle(valueX); + auto yHandle = JSHandle(valueY); + int result = EcmaStringAccessor::Compare(thread->GetEcmaVM(), xHandle, yHandle); if (result < 0) { return ComparisonResult::LESS; } diff --git a/ecmascript/tests/dump_test.cpp b/ecmascript/tests/dump_test.cpp index 0bf735441e..7b8e1a57b2 100644 --- a/ecmascript/tests/dump_test.cpp +++ b/ecmascript/tests/dump_test.cpp @@ -778,7 +778,8 @@ HWTEST_F_L0(EcmaDumpTest, HeapProfileDump) DUMP_FOR_HANDLE(hclass) break; } - case JSType::STRING: { + case JSType::LINE_STRING: + case JSType::TREE_STRING: { DUMP_FOR_HANDLE(globalEnv->GetObjectFunction()) break; } diff --git a/ecmascript/tests/ecma_string_accessor_test.cpp b/ecmascript/tests/ecma_string_accessor_test.cpp index f00bcc1bd2..7f83c2c4b3 100644 --- a/ecmascript/tests/ecma_string_accessor_test.cpp +++ b/ecmascript/tests/ecma_string_accessor_test.cpp @@ -20,6 +20,63 @@ using namespace panda::ecmascript; namespace panda::test { +class LineEcmaStringTest : public testing::Test { +public: + static void SetUpTestCase() + { + GTEST_LOG_(INFO) << "SetUpTestCase"; + } + + static void TearDownTestCase() + { + GTEST_LOG_(INFO) << "TearDownCase"; + } + + void SetUp() override + { + TestHelper::CreateEcmaVMWithScope(ecmaVMPtr, thread, scope); + } + + void TearDown() override + { + TestHelper::DestroyEcmaVMWithScope(ecmaVMPtr, scope); + } + + EcmaVM *ecmaVMPtr {nullptr}; + ecmascript::EcmaHandleScope *scope {nullptr}; + JSThread *thread {nullptr}; +}; + +/* + * @tc.name: ComputeSizeUtf8 + * @tc.desc: Check whether the value returned through calling ComputeSizeUtf8 function is within expectations. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F_L0(LineEcmaStringTest, ComputeSizeUtf8) +{ + uint32_t scale = 3333; + for (uint32_t i = 0x40000000U - 1; i > scale; i = i - scale) { + uint32_t length = i; + EXPECT_EQ(LineEcmaString::ComputeSizeUtf8(length), length + LineEcmaString::SIZE); + } +} + +/* + * @tc.name: ComputeSizeUtf16 + * @tc.desc: Check whether the value returned through calling ComputeSizeUtf16 function is within expectations. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F_L0(LineEcmaStringTest, ComputeSizeUtf16) +{ + uint32_t scale = 3333; + for (uint32_t i = 0x40000000U - 1; i > scale; i = i - scale) { + uint32_t length = i; + EXPECT_EQ(LineEcmaString::ComputeSizeUtf16(length), 2 * length + LineEcmaString::SIZE); + } +} + class EcmaStringAccessorTest : public testing::Test { public: static void SetUpTestCase() @@ -48,17 +105,17 @@ public: }; /* - * @tc.name: AllocStringObject - * @tc.desc: Check whether the EcmaString created through calling AllocStringObject function is within expectations. + * @tc.name: CreateLineString + * @tc.desc: Check whether the EcmaString created through calling CreateLineString function is within expectations. * @tc.type: FUNC * @tc.require: */ -HWTEST_F_L0(EcmaStringAccessorTest, AllocStringObject) +HWTEST_F_L0(EcmaStringAccessorTest, CreateLineString) { - // AllocStringObject( , true, ). + // CreateLineString( , true, ). size_t sizeAllocComp = 5; JSHandle handleEcmaStrAllocComp(thread, - EcmaStringAccessor::AllocStringObject(ecmaVMPtr, sizeAllocComp, true)); + EcmaStringAccessor::CreateLineString(ecmaVMPtr, sizeAllocComp, true)); for (uint32_t i = 0; i < sizeAllocComp; i++) { EXPECT_EQ(EcmaStringAccessor(handleEcmaStrAllocComp).Get(i), 0U); } @@ -66,10 +123,10 @@ HWTEST_F_L0(EcmaStringAccessorTest, AllocStringObject) EXPECT_TRUE(EcmaStringAccessor(handleEcmaStrAllocComp).IsUtf8()); EXPECT_FALSE(EcmaStringAccessor(handleEcmaStrAllocComp).IsUtf16()); - // AllocStringObject( , false, ). + // CreateLineString( , false, ). size_t sizeAllocNotComp = 5; JSHandle handleEcmaStrAllocNotComp(thread, - EcmaStringAccessor::AllocStringObject(ecmaVMPtr, sizeAllocNotComp, false)); + EcmaStringAccessor::CreateLineString(ecmaVMPtr, sizeAllocNotComp, false)); for (uint32_t i = 0; i < sizeAllocNotComp; i++) { EXPECT_EQ(EcmaStringAccessor(handleEcmaStrAllocNotComp).Get(i), 0U); } @@ -389,13 +446,13 @@ HWTEST_F_L0(EcmaStringAccessorTest, ObjectSize) size_t lengthEcmaStrAllocComp = 5; JSHandle handleEcmaStrAllocComp(thread, - EcmaStringAccessor::AllocStringObject(ecmaVMPtr, lengthEcmaStrAllocComp, true)); + EcmaStringAccessor::CreateLineString(ecmaVMPtr, lengthEcmaStrAllocComp, true)); EXPECT_EQ(EcmaStringAccessor(handleEcmaStrAllocComp).ObjectSize(), EcmaString::SIZE + sizeof(uint8_t) * lengthEcmaStrAllocComp); size_t lengthEcmaStrAllocNotComp = 5; JSHandle handleEcmaStrAllocNotComp(thread, - EcmaStringAccessor::AllocStringObject(ecmaVMPtr, lengthEcmaStrAllocNotComp, false)); + EcmaStringAccessor::CreateLineString(ecmaVMPtr, lengthEcmaStrAllocNotComp, false)); EXPECT_EQ(EcmaStringAccessor(handleEcmaStrAllocNotComp).ObjectSize(), EcmaString::SIZE + sizeof(uint16_t) * lengthEcmaStrAllocNotComp); @@ -580,21 +637,21 @@ HWTEST_F_L0(EcmaStringAccessorTest, WriteToFlatUtf16) /* * @tc.name: ReadData_001 - * @tc.desc: Check whether the target EcmaString made by AllocStringObject( , true, ) changed through calling ReadData + * @tc.desc: Check whether the target EcmaString made by CreateLineString( , true, ) changed through calling ReadData * function with a source EcmaString made by CreateFromUtf8() is within expectations. * @tc.type: FUNC * @tc.require: */ HWTEST_F_L0(EcmaStringAccessorTest, ReadData_001) { - // ReadData(). From EcmaString made by CreateFromUtf8() to EcmaString made by AllocStringObject( , true, ). + // ReadData(). From EcmaString made by CreateFromUtf8() to EcmaString made by CreateLineString( , true, ). uint8_t arrayU8WriteFrom[6] = {1, 12, 34, 56, 127}; uint32_t lengthEcmaStrU8WriteFrom = sizeof(arrayU8WriteFrom) - 1; JSHandle handleEcmaStrU8WriteFrom(thread, EcmaStringAccessor::CreateFromUtf8(ecmaVMPtr, &arrayU8WriteFrom[0], lengthEcmaStrU8WriteFrom, true)); size_t sizeEcmaStrU8WriteTo = 5; JSHandle handleEcmaStrAllocTrueWriteTo(thread, - EcmaStringAccessor::AllocStringObject(ecmaVMPtr, sizeEcmaStrU8WriteTo, true)); + EcmaStringAccessor::CreateLineString(ecmaVMPtr, sizeEcmaStrU8WriteTo, true)); uint32_t indexStartWriteFromArrayU8 = 2; uint32_t lengthWriteFromArrayU8 = 2; EcmaStringAccessor::ReadData(*handleEcmaStrAllocTrueWriteTo, *handleEcmaStrU8WriteFrom, indexStartWriteFromArrayU8, @@ -607,7 +664,7 @@ HWTEST_F_L0(EcmaStringAccessorTest, ReadData_001) /* * @tc.name: ReadData_002 - * @tc.desc: Check whether the target EcmaString made by AllocStringObject( , false, ) changed through calling + * @tc.desc: Check whether the target EcmaString made by CreateLineString( , false, ) changed through calling * ReadData function with a source EcmaString made by CreateFromUtf16( , , , false) is within expectations. * @tc.type: FUNC * @tc.require: @@ -615,7 +672,7 @@ HWTEST_F_L0(EcmaStringAccessorTest, ReadData_001) HWTEST_F_L0(EcmaStringAccessorTest, ReadData_002) { /* ReadData(). From EcmaString made by CreateFromUtf16( , , , false) to EcmaStringU16 made by - * AllocStringObject( , false, ). + * CreateLineString( , false, ). */ uint16_t arrayU16WriteFrom[10] = {67, 777, 1999, 1, 45, 66, 23456, 65535, 127, 333}; uint32_t lengthEcmaStrU16WriteFrom = sizeof(arrayU16WriteFrom) / sizeof(arrayU16WriteFrom[0]); @@ -623,7 +680,7 @@ HWTEST_F_L0(EcmaStringAccessorTest, ReadData_002) EcmaStringAccessor::CreateFromUtf16(ecmaVMPtr, &arrayU16WriteFrom[0], lengthEcmaStrU16WriteFrom, false)); size_t sizeEcmaStrU16WriteTo = 10; JSHandle handleEcmaStrU16WriteTo(thread, - EcmaStringAccessor::AllocStringObject(ecmaVMPtr, sizeEcmaStrU16WriteTo, false)); + EcmaStringAccessor::CreateLineString(ecmaVMPtr, sizeEcmaStrU16WriteTo, false)); uint32_t indexStartWriteFromArrayU16 = 3; uint32_t numBytesWriteFromArrayU16 = 2 * 3; EcmaStringAccessor::ReadData(*handleEcmaStrU16WriteTo, *handleEcmaStrU16WriteFrom, indexStartWriteFromArrayU16, @@ -636,21 +693,21 @@ HWTEST_F_L0(EcmaStringAccessorTest, ReadData_002) /* * @tc.name: ReadData_003 - * @tc.desc: Check whether the target EcmaString made by AllocStringObject( , false, ) changed through calling + * @tc.desc: Check whether the target EcmaString made by CreateLineString( , false, ) changed through calling * ReadData function with a source EcmaString made by CreateFromUtf8() is within expectations. * @tc.type: FUNC * @tc.require: */ HWTEST_F_L0(EcmaStringAccessorTest, ReadData_003) { - // WriteData(). From EcmaString made by CreateFromUtf8() to EcmaString made by AllocStringObject( , false, ). + // ReadData(). From EcmaString made by CreateFromUtf8() to EcmaString made by CreateLineString( , false, ). uint8_t arrayU8WriteFrom[6] = {1, 12, 34, 56, 127}; uint32_t lengthEcmaStrU8WriteFrom = sizeof(arrayU8WriteFrom) - 1; JSHandle handleEcmaStrU8WriteFrom(thread, EcmaStringAccessor::CreateFromUtf8(ecmaVMPtr, &arrayU8WriteFrom[0], lengthEcmaStrU8WriteFrom, true)); size_t sizeEcmaStrU16WriteTo = 10; JSHandle handleEcmaStrU16WriteTo(thread, - EcmaStringAccessor::AllocStringObject(ecmaVMPtr, sizeEcmaStrU16WriteTo, false)); + EcmaStringAccessor::CreateLineString(ecmaVMPtr, sizeEcmaStrU16WriteTo, false)); uint32_t indexStartWriteFromU8ToU16 = 1; uint32_t numBytesWriteFromU8ToU16 = 4; EcmaStringAccessor::ReadData(*handleEcmaStrU16WriteTo, *handleEcmaStrU8WriteFrom, @@ -664,18 +721,18 @@ HWTEST_F_L0(EcmaStringAccessorTest, ReadData_003) /* * @tc.name: Set_001 - * @tc.desc: Check whether the target EcmaString made by AllocStringObject( , true, ) changed through calling Set + * @tc.desc: Check whether the target EcmaString made by CreateLineString( , true, ) changed through calling Set * function from a source char is within expectations. * @tc.type: FUNC * @tc.require: */ HWTEST_F_L0(EcmaStringAccessorTest, Set_001) { - // Set(). From char to EcmaString made by AllocStringObject( , true, ). + // Set(). From char to EcmaString made by CreateLineString( , true, ). char u8Write = 'a'; size_t sizeEcmaStrU8WriteTo = 5; JSHandle handleEcmaStrAllocTrueWriteTo(thread, - EcmaStringAccessor::AllocStringObject(ecmaVMPtr, sizeEcmaStrU8WriteTo, true)); + EcmaStringAccessor::CreateLineString(ecmaVMPtr, sizeEcmaStrU8WriteTo, true)); uint32_t indexAtWriteFromU8 = 4; EcmaStringAccessor(handleEcmaStrAllocTrueWriteTo).Set(indexAtWriteFromU8, u8Write); EXPECT_EQ(EcmaStringAccessor(handleEcmaStrAllocTrueWriteTo).Get(indexAtWriteFromU8), u8Write); @@ -683,17 +740,17 @@ HWTEST_F_L0(EcmaStringAccessorTest, Set_001) /* * @tc.name: Set_002 - * @tc.desc: Check whether the target EcmaString made by AllocStringObject( , false, ) changed through calling + * @tc.desc: Check whether the target EcmaString made by CreateLineString( , false, ) changed through calling * Set function with a source char is within expectations. * @tc.type: FUNC * @tc.require: */ HWTEST_F_L0(EcmaStringAccessorTest, Set_002) { - // Set(). From char to EcmaString made by AllocStringObject( , false, ). + // Set(). From char to EcmaString made by CreateLineString( , false, ). size_t sizeEcmaStrU16WriteTo = 10; JSHandle handleEcmaStrU16WriteTo(thread, - EcmaStringAccessor::AllocStringObject(ecmaVMPtr, sizeEcmaStrU16WriteTo, false)); + EcmaStringAccessor::CreateLineString(ecmaVMPtr, sizeEcmaStrU16WriteTo, false)); char u8Write = 'a'; uint32_t indexAt = 4; EcmaStringAccessor(handleEcmaStrU16WriteTo).Set(indexAt, u8Write); @@ -779,19 +836,19 @@ HWTEST_F_L0(EcmaStringAccessorTest, GetHashcode_004) /* * @tc.name: GetHashcode_005 - * @tc.desc: Check whether the value returned through an EcmaString made by AllocStringObject(, true/false, ) calling + * @tc.desc: Check whether the value returned through an EcmaString made by CreateLineString(, true/false, ) calling * GetHashcode function is within expectations. * @tc.type: FUNC * @tc.require: */ HWTEST_F_L0(EcmaStringAccessorTest, GetHashcode_005) { - // GetHashcode(). EcmaString made by AllocStringObject(). + // GetHashcode(). EcmaString made by CreateLineString(). size_t sizeAlloc = 5; JSHandle handleEcmaStrAllocComp(thread, - EcmaStringAccessor::AllocStringObject(ecmaVMPtr, sizeAlloc, true)); + EcmaStringAccessor::CreateLineString(ecmaVMPtr, sizeAlloc, true)); JSHandle handleEcmaStrAllocNotComp(thread, - EcmaStringAccessor::AllocStringObject(ecmaVMPtr, sizeAlloc, false)); + EcmaStringAccessor::CreateLineString(ecmaVMPtr, sizeAlloc, false)); EXPECT_EQ(EcmaStringAccessor(handleEcmaStrAllocComp).GetHashcode(), 0U); EXPECT_EQ(EcmaStringAccessor(handleEcmaStrAllocNotComp).GetHashcode(), 0U); } @@ -851,16 +908,16 @@ HWTEST_F_L0(EcmaStringAccessorTest, IndexOf_001) JSHandle handleEcmaStr1(thread, EcmaStringAccessor::CreateFromUtf8(ecmaVMPtr, &arrayU8Target[0], lengthEcmaStrU8Target, true)); int32_t posStart = 0; - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStr, *handleEcmaStr1, posStart), 2); - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStr1, *handleEcmaStr, posStart), -1); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, handleEcmaStr, handleEcmaStr1, posStart), 2); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, handleEcmaStr1, handleEcmaStr, posStart), -1); posStart = -1; - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStr, *handleEcmaStr1, posStart), 2); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, handleEcmaStr, handleEcmaStr1, posStart), 2); posStart = 1; - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStr, *handleEcmaStr1, posStart), 2); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, handleEcmaStr, handleEcmaStr1, posStart), 2); posStart = 2; - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStr, *handleEcmaStr1, posStart), 2); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, handleEcmaStr, handleEcmaStr1, posStart), 2); posStart = 3; - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStr, *handleEcmaStr1, posStart), -1); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, handleEcmaStr, handleEcmaStr1, posStart), -1); } /* @@ -882,16 +939,16 @@ HWTEST_F_L0(EcmaStringAccessorTest, IndexOf_002) JSHandle handleEcmaStr1(thread, EcmaStringAccessor::CreateFromUtf16( ecmaVMPtr, &arrayU16NotCompFromNo1[0], lengthEcmaStrU16NotCompFromNo1, false)); int32_t posStart = 0; - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStr1, *handleEcmaStr, posStart), 6); - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStr, *handleEcmaStr1, posStart), -1); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, handleEcmaStr1, handleEcmaStr, posStart), 6); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, handleEcmaStr, handleEcmaStr1, posStart), -1); posStart = -1; - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStr1, *handleEcmaStr, posStart), 6); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, handleEcmaStr1, handleEcmaStr, posStart), 6); posStart = 1; - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStr1, *handleEcmaStr, posStart), 6); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, handleEcmaStr1, handleEcmaStr, posStart), 6); posStart = 6; - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStr1, *handleEcmaStr, posStart), 6); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, handleEcmaStr1, handleEcmaStr, posStart), 6); posStart = 7; - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStr1, *handleEcmaStr, posStart), -1); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, handleEcmaStr1, handleEcmaStr, posStart), -1); } /* @@ -915,16 +972,22 @@ HWTEST_F_L0(EcmaStringAccessorTest, IndexOf_003) JSHandle handleEcmaStrU16NotCompFrom(thread, EcmaStringAccessor::CreateFromUtf16(ecmaVMPtr, &arrayU16NotCompFrom[0], lengthEcmaStrU16NotCompFrom, false)); int32_t posStart = 0; - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStrU16NotCompFrom, *handleEcmaStrU16NotCompTarget, posStart), 4); - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStrU16NotCompTarget, *handleEcmaStrU16NotCompFrom, posStart), -1); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, + handleEcmaStrU16NotCompFrom, handleEcmaStrU16NotCompTarget, posStart), 4); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, + handleEcmaStrU16NotCompTarget, handleEcmaStrU16NotCompFrom, posStart), -1); posStart = -1; - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStrU16NotCompFrom, *handleEcmaStrU16NotCompTarget, posStart), 4); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, + handleEcmaStrU16NotCompFrom, handleEcmaStrU16NotCompTarget, posStart), 4); posStart = 1; - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStrU16NotCompFrom, *handleEcmaStrU16NotCompTarget, posStart), 4); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, + handleEcmaStrU16NotCompFrom, handleEcmaStrU16NotCompTarget, posStart), 4); posStart = 4; - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStrU16NotCompFrom, *handleEcmaStrU16NotCompTarget, posStart), 4); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, + handleEcmaStrU16NotCompFrom, handleEcmaStrU16NotCompTarget, posStart), 4); posStart = 5; - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStrU16NotCompFrom, *handleEcmaStrU16NotCompTarget, posStart), -1); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, + handleEcmaStrU16NotCompFrom, handleEcmaStrU16NotCompTarget, posStart), -1); } /* @@ -946,16 +1009,22 @@ HWTEST_F_L0(EcmaStringAccessorTest, IndexOf_004) JSHandle handleEcmaStrU8From(thread, EcmaStringAccessor::CreateFromUtf8(ecmaVMPtr, &arrayU8From[0], lengthEcmaStrU8From, true)); int32_t posStart = 0; - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStrU8From, *handleEcmaStrU16NotCompTarget, posStart), 3); - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStrU16NotCompTarget, *handleEcmaStrU8From, posStart), -1); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, + handleEcmaStrU8From, handleEcmaStrU16NotCompTarget, posStart), 3); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, + handleEcmaStrU16NotCompTarget, handleEcmaStrU8From, posStart), -1); posStart = -1; - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStrU8From, *handleEcmaStrU16NotCompTarget, posStart), 3); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, + handleEcmaStrU8From, handleEcmaStrU16NotCompTarget, posStart), 3); posStart = 1; - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStrU8From, *handleEcmaStrU16NotCompTarget, posStart), 3); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, + handleEcmaStrU8From, handleEcmaStrU16NotCompTarget, posStart), 3); posStart = 3; - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStrU8From, *handleEcmaStrU16NotCompTarget, posStart), 3); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, + handleEcmaStrU8From, handleEcmaStrU16NotCompTarget, posStart), 3); posStart = 4; - EXPECT_EQ(EcmaStringAccessor::IndexOf(*handleEcmaStrU8From, *handleEcmaStrU16NotCompTarget, posStart), -1); + EXPECT_EQ(EcmaStringAccessor::IndexOf(ecmaVMPtr, + handleEcmaStrU8From, handleEcmaStrU16NotCompTarget, posStart), -1); } /* @@ -980,10 +1049,10 @@ HWTEST_F_L0(EcmaStringAccessorTest, Compare_001) EcmaStringAccessor::CreateFromUtf8(ecmaVMPtr, &arrayU8No2[0], lengthEcmaStrU8No2, true)); JSHandle handleEcmaStrU8No3(thread, EcmaStringAccessor::CreateFromUtf8(ecmaVMPtr, &arrayU8No3[0], lengthEcmaStrU8No3, true)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU8No1, *handleEcmaStrU8No2), -1); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU8No2, *handleEcmaStrU8No1), 1); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU8No2, *handleEcmaStrU8No3), 49 - 45); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU8No3, *handleEcmaStrU8No2), 45 - 49); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU8No1, handleEcmaStrU8No2), -1); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU8No2, handleEcmaStrU8No1), 1); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU8No2, handleEcmaStrU8No3), 49 - 45); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU8No3, handleEcmaStrU8No2), 45 - 49); } /* @@ -1008,10 +1077,10 @@ HWTEST_F_L0(EcmaStringAccessorTest, Compare_002) EcmaStringAccessor::CreateFromUtf16(ecmaVMPtr, &arrayU16CompNo2[0], lengthEcmaStrU16CompNo2, true)); JSHandle handleEcmaStrU16CompNo3(thread, EcmaStringAccessor::CreateFromUtf16(ecmaVMPtr, &arrayU16CompNo3[0], lengthEcmaStrU16CompNo3, true)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU16CompNo1, *handleEcmaStrU16CompNo2), -1); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU16CompNo2, *handleEcmaStrU16CompNo1), 1); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU16CompNo2, *handleEcmaStrU16CompNo3), 49 - 45); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU16CompNo3, *handleEcmaStrU16CompNo2), 45 - 49); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU16CompNo1, handleEcmaStrU16CompNo2), -1); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU16CompNo2, handleEcmaStrU16CompNo1), 1); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU16CompNo2, handleEcmaStrU16CompNo3), 49 - 45); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU16CompNo3, handleEcmaStrU16CompNo2), 45 - 49); } /* @@ -1045,12 +1114,12 @@ HWTEST_F_L0(EcmaStringAccessorTest, Compare_003) EcmaStringAccessor::CreateFromUtf16(ecmaVMPtr, &arrayU16CompNo2[0], lengthEcmaStrU16CompNo2, true)); JSHandle handleEcmaStrU16CompNo3(thread, EcmaStringAccessor::CreateFromUtf16(ecmaVMPtr, &arrayU16CompNo3[0], lengthEcmaStrU16CompNo3, true)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU8No1, *handleEcmaStrU16CompNo1), 0); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU16CompNo1, *handleEcmaStrU8No1), 0); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU8No1, *handleEcmaStrU16CompNo2), -1); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU16CompNo2, *handleEcmaStrU8No1), 1); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU8No2, *handleEcmaStrU16CompNo3), 49 - 45); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU16CompNo3, *handleEcmaStrU8No2), 45 - 49); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU8No1, handleEcmaStrU16CompNo1), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU16CompNo1, handleEcmaStrU8No1), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU8No1, handleEcmaStrU16CompNo2), -1); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU16CompNo2, handleEcmaStrU8No1), 1); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU8No2, handleEcmaStrU16CompNo3), 49 - 45); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU16CompNo3, handleEcmaStrU8No2), 45 - 49); } /* @@ -1075,10 +1144,10 @@ HWTEST_F_L0(EcmaStringAccessorTest, Compare_004) EcmaStringAccessor::CreateFromUtf16(ecmaVMPtr, &arrayU16NotCompNo2[0], lengthEcmaStrU16NotCompNo2, true)); JSHandle handleEcmaStrU16NotCompNo3(thread, EcmaStringAccessor::CreateFromUtf16(ecmaVMPtr, &arrayU16NotCompNo3[0], lengthEcmaStrU16NotCompNo3, false)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU16NotCompNo1, *handleEcmaStrU16NotCompNo2), -1); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU16NotCompNo2, *handleEcmaStrU16NotCompNo1), 1); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU16NotCompNo2, *handleEcmaStrU16NotCompNo3), 49 - 456); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU16NotCompNo3, *handleEcmaStrU16NotCompNo2), 456 - 49); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU16NotCompNo1, handleEcmaStrU16NotCompNo2), -1); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU16NotCompNo2, handleEcmaStrU16NotCompNo1), 1); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU16NotCompNo2, handleEcmaStrU16NotCompNo3), 49 - 456); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU16NotCompNo3, handleEcmaStrU16NotCompNo2), 456 - 49); } /* @@ -1111,12 +1180,12 @@ HWTEST_F_L0(EcmaStringAccessorTest, Compare_005) EcmaStringAccessor::CreateFromUtf16(ecmaVMPtr, &arrayU16NotCompNo2[0], lengthEcmaStrU16NotCompNo2, true)); JSHandle handleEcmaStrU16NotCompNo3(thread, EcmaStringAccessor::CreateFromUtf16(ecmaVMPtr, &arrayU16NotCompNo3[0], lengthEcmaStrU16NotCompNo3, false)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU8No1, *handleEcmaStrU16NotCompNo1), 0); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU16NotCompNo1, *handleEcmaStrU8No1), 0); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU8No1, *handleEcmaStrU16NotCompNo2), -1); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU16NotCompNo2, *handleEcmaStrU8No1), 1); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU8No2, *handleEcmaStrU16NotCompNo3), 49 - 456); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU16NotCompNo3, *handleEcmaStrU8No2), 456 - 49); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU8No1, handleEcmaStrU16NotCompNo1), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU16NotCompNo1, handleEcmaStrU8No1), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU8No1, handleEcmaStrU16NotCompNo2), -1); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU16NotCompNo2, handleEcmaStrU8No1), 1); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU8No2, handleEcmaStrU16NotCompNo3), 49 - 456); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU16NotCompNo3, handleEcmaStrU8No2), 456 - 49); } /* @@ -1149,12 +1218,12 @@ HWTEST_F_L0(EcmaStringAccessorTest, Compare_006) EcmaStringAccessor::CreateFromUtf16(ecmaVMPtr, &arrayU16NotCompNo2[0], lengthEcmaStrU16NotCompNo2, true)); JSHandle handleEcmaStrU16NotCompNo3(thread, EcmaStringAccessor::CreateFromUtf16(ecmaVMPtr, &arrayU16NotCompNo3[0], lengthEcmaStrU16NotCompNo3, false)); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU16CompNo1, *handleEcmaStrU16NotCompNo1), 0); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU16NotCompNo1, *handleEcmaStrU16CompNo1), 0); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU16CompNo1, *handleEcmaStrU16NotCompNo2), -1); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU16NotCompNo2, *handleEcmaStrU16CompNo1), 1); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU16CompNo2, *handleEcmaStrU16NotCompNo3), 49 - 456); - EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStrU16NotCompNo3, *handleEcmaStrU16CompNo2), 456 - 49); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU16CompNo1, handleEcmaStrU16NotCompNo1), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU16NotCompNo1, handleEcmaStrU16CompNo1), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU16CompNo1, handleEcmaStrU16NotCompNo2), -1); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU16NotCompNo2, handleEcmaStrU16CompNo1), 1); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU16CompNo2, handleEcmaStrU16NotCompNo3), 49 - 456); + EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVMPtr, handleEcmaStrU16NotCompNo3, handleEcmaStrU16CompNo2), 456 - 49); } /* diff --git a/ecmascript/tests/ecma_string_test.cpp b/ecmascript/tests/ecma_string_test.cpp index 8faec25cff..c126b79f9e 100644 --- a/ecmascript/tests/ecma_string_test.cpp +++ b/ecmascript/tests/ecma_string_test.cpp @@ -84,16 +84,16 @@ HWTEST_F_L0(EcmaStringTest, CreateEmptyString) } /* - * @tc.name: AllocStringObject - * @tc.desc: Check whether the EcmaString created through calling AllocStringObject function is within expectations. + * @tc.name: CreateLineString + * @tc.desc: Check whether the EcmaString created through calling CreateLineString function is within expectations. * @tc.type: FUNC * @tc.require: */ -HWTEST_F_L0(EcmaStringTest, AllocStringObject) +HWTEST_F_L0(EcmaStringTest, CreateLineString) { - // AllocStringObject( , true, ). + // CreateLineString( , true, ). size_t sizeAllocComp = 5; - JSHandle handleEcmaStrAllocComp(thread, EcmaString::AllocStringObject(ecmaVMPtr, sizeAllocComp, true)); + JSHandle handleEcmaStrAllocComp(thread, EcmaString::CreateLineString(ecmaVMPtr, sizeAllocComp, true)); for (uint32_t i = 0; i < sizeAllocComp; i++) { EXPECT_EQ(handleEcmaStrAllocComp->At(i), 0U); } @@ -101,10 +101,10 @@ HWTEST_F_L0(EcmaStringTest, AllocStringObject) EXPECT_TRUE(handleEcmaStrAllocComp->IsUtf8()); EXPECT_FALSE(handleEcmaStrAllocComp->IsUtf16()); - // AllocStringObject( , false, ). + // CreateLineString( , false, ). size_t sizeAllocNotComp = 5; JSHandle handleEcmaStrAllocNotComp(thread, - EcmaString::AllocStringObject(ecmaVMPtr, sizeAllocNotComp, false)); + EcmaString::CreateLineString(ecmaVMPtr, sizeAllocNotComp, false)); for (uint32_t i = 0; i < sizeAllocNotComp; i++) { EXPECT_EQ(handleEcmaStrAllocNotComp->At(i), 0U); } @@ -160,51 +160,6 @@ HWTEST_F_L0(EcmaStringTest, CreateFromUtf16) EXPECT_TRUE(handleEcmaStrU16NotComp->IsUtf16()); } -/* - * @tc.name: ComputeSizeUtf8 - * @tc.desc: Check whether the value returned through calling ComputeSizeUtf8 function is within expectations. - * @tc.type: FUNC - * @tc.require: - */ -HWTEST_F_L0(EcmaStringTest, ComputeSizeUtf8) -{ - uint32_t scale = 3333; - for (uint32_t i = 0x40000000U - 1; i > scale; i = i - scale) { - uint32_t length = i; - EXPECT_EQ(EcmaString::ComputeSizeUtf8(length), length + EcmaString::SIZE); - } -} - -/* - * @tc.name: ComputeDataSizeUtf16 - * @tc.desc: Check whether the value returned through calling ComputeDataSizeUtf16 function is within expectations. - * @tc.type: FUNC - * @tc.require: - */ -HWTEST_F_L0(EcmaStringTest, ComputeDataSizeUtf16) -{ - uint32_t scale = 3333; - for (uint32_t i = 0x40000000U - 1; i > scale; i = i - scale) { - uint32_t length = i; - EXPECT_EQ(EcmaString::ComputeDataSizeUtf16(length), 2 * length); - } -} - -/* - * @tc.name: ComputeSizeUtf16 - * @tc.desc: Check whether the value returned through calling ComputeSizeUtf16 function is within expectations. - * @tc.type: FUNC - * @tc.require: - */ -HWTEST_F_L0(EcmaStringTest, ComputeSizeUtf16) -{ - uint32_t scale = 3333; - for (uint32_t i = 0x40000000U - 1; i > scale; i = i - scale) { - uint32_t length = i; - EXPECT_EQ(EcmaString::ComputeSizeUtf16(length), 2 * length + EcmaString::SIZE); - } -} - /* * @tc.name: ObjectSize * @tc.desc: Check whether the value returned through calling ObjectSize function is within expectations. @@ -218,12 +173,12 @@ HWTEST_F_L0(EcmaStringTest, ObjectSize) size_t lengthEcmaStrAllocComp = 5; JSHandle handleEcmaStrAllocComp(thread, - EcmaString::AllocStringObject(ecmaVMPtr, lengthEcmaStrAllocComp, true)); + EcmaString::CreateLineString(ecmaVMPtr, lengthEcmaStrAllocComp, true)); EXPECT_EQ(handleEcmaStrAllocComp->ObjectSize(), EcmaString::SIZE + sizeof(uint8_t) * lengthEcmaStrAllocComp); size_t lengthEcmaStrAllocNotComp = 5; JSHandle handleEcmaStrAllocNotComp(thread, - EcmaString::AllocStringObject(ecmaVMPtr, lengthEcmaStrAllocNotComp, false)); + EcmaString::CreateLineString(ecmaVMPtr, lengthEcmaStrAllocNotComp, false)); EXPECT_EQ(handleEcmaStrAllocNotComp->ObjectSize(), EcmaString::SIZE + sizeof(uint16_t) * lengthEcmaStrAllocNotComp); @@ -654,21 +609,21 @@ HWTEST_F_L0(EcmaStringTest, FastSubString_004) /* * @tc.name: WriteData_001 - * @tc.desc: Check whether the target EcmaString made by AllocStringObject( , true, ) changed through calling WriteData + * @tc.desc: Check whether the target EcmaString made by CreateLineString( , true, ) changed through calling WriteData * function with a source EcmaString made by CreateFromUtf8() is within expectations. * @tc.type: FUNC * @tc.require: */ HWTEST_F_L0(EcmaStringTest, WriteData_001) { - // WriteData(). From EcmaString made by CreateFromUtf8() to EcmaString made by AllocStringObject( , true, ). + // WriteData(). From EcmaString made by CreateFromUtf8() to EcmaString made by CreateLineString( , true, ). uint8_t arrayU8WriteFrom[6] = {1, 12, 34, 56, 127}; uint32_t lengthEcmaStrU8WriteFrom = sizeof(arrayU8WriteFrom) - 1; JSHandle handleEcmaStrU8WriteFrom(thread, EcmaString::CreateFromUtf8(ecmaVMPtr, &arrayU8WriteFrom[0], lengthEcmaStrU8WriteFrom, true)); size_t sizeEcmaStrU8WriteTo = 5; JSHandle handleEcmaStrAllocTrueWriteTo(thread, - EcmaString::AllocStringObject(ecmaVMPtr, sizeEcmaStrU8WriteTo, true)); + EcmaString::CreateLineString(ecmaVMPtr, sizeEcmaStrU8WriteTo, true)); uint32_t indexStartWriteFromArrayU8 = 2; uint32_t lengthWriteFromArrayU8 = 2; handleEcmaStrAllocTrueWriteTo->WriteData(*handleEcmaStrU8WriteFrom, indexStartWriteFromArrayU8, @@ -680,18 +635,18 @@ HWTEST_F_L0(EcmaStringTest, WriteData_001) /* * @tc.name: WriteData_002 - * @tc.desc: Check whether the target EcmaString made by AllocStringObject( , true, ) changed through calling WriteData + * @tc.desc: Check whether the target EcmaString made by CreateLineString( , true, ) changed through calling WriteData * function from a source char is within expectations. * @tc.type: FUNC * @tc.require: */ HWTEST_F_L0(EcmaStringTest, WriteData_002) { - // WriteData(). From char to EcmaString made by AllocStringObject( , true, ). + // WriteData(). From char to EcmaString made by CreateLineString( , true, ). char u8Write = 'a'; size_t sizeEcmaStrU8WriteTo = 5; JSHandle handleEcmaStrAllocTrueWriteTo(thread, - EcmaString::AllocStringObject(ecmaVMPtr, sizeEcmaStrU8WriteTo, true)); + EcmaString::CreateLineString(ecmaVMPtr, sizeEcmaStrU8WriteTo, true)); uint32_t indexAtWriteFromU8 = 4; handleEcmaStrAllocTrueWriteTo->WriteData(u8Write, indexAtWriteFromU8); EXPECT_EQ(handleEcmaStrAllocTrueWriteTo->At(indexAtWriteFromU8), u8Write); @@ -699,7 +654,7 @@ HWTEST_F_L0(EcmaStringTest, WriteData_002) /* * @tc.name: WriteData_003 - * @tc.desc: Check whether the target EcmaString made by AllocStringObject( , false, ) changed through calling + * @tc.desc: Check whether the target EcmaString made by CreateLineString( , false, ) changed through calling * WriteData function with a source EcmaString made by CreateFromUtf16( , , , false) is within expectations. * @tc.type: FUNC * @tc.require: @@ -707,7 +662,7 @@ HWTEST_F_L0(EcmaStringTest, WriteData_002) HWTEST_F_L0(EcmaStringTest, WriteData_003) { /* WriteData(). From EcmaString made by CreateFromUtf16( , , , false) to EcmaStringU16 made by - * AllocStringObject( , false, ). + * CreateLineString( , false, ). */ uint16_t arrayU16WriteFrom[10] = {67, 777, 1999, 1, 45, 66, 23456, 65535, 127, 333}; uint32_t lengthEcmaStrU16WriteFrom = sizeof(arrayU16WriteFrom) / sizeof(arrayU16WriteFrom[0]); @@ -715,7 +670,7 @@ HWTEST_F_L0(EcmaStringTest, WriteData_003) EcmaString::CreateFromUtf16(ecmaVMPtr, &arrayU16WriteFrom[0], lengthEcmaStrU16WriteFrom, false)); size_t sizeEcmaStrU16WriteTo = 10; JSHandle handleEcmaStrU16WriteTo(thread, - EcmaString::AllocStringObject(ecmaVMPtr, sizeEcmaStrU16WriteTo, false)); + EcmaString::CreateLineString(ecmaVMPtr, sizeEcmaStrU16WriteTo, false)); uint32_t indexStartWriteFromArrayU16 = 3; uint32_t numBytesWriteFromArrayU16 = 2 * 3; handleEcmaStrU16WriteTo->WriteData(*handleEcmaStrU16WriteFrom, indexStartWriteFromArrayU16, sizeEcmaStrU16WriteTo, @@ -727,21 +682,21 @@ HWTEST_F_L0(EcmaStringTest, WriteData_003) /* * @tc.name: WriteData_004 - * @tc.desc: Check whether the target EcmaString made by AllocStringObject( , false, ) changed through calling + * @tc.desc: Check whether the target EcmaString made by CreateLineString( , false, ) changed through calling * WriteData function with a source EcmaString made by CreateFromUtf8() is within expectations. * @tc.type: FUNC * @tc.require: */ HWTEST_F_L0(EcmaStringTest, WriteData_004) { - // WriteData(). From EcmaString made by CreateFromUtf8() to EcmaString made by AllocStringObject( , false, ). + // WriteData(). From EcmaString made by CreateFromUtf8() to EcmaString made by CreateLineString( , false, ). uint8_t arrayU8WriteFrom[6] = {1, 12, 34, 56, 127}; uint32_t lengthEcmaStrU8WriteFrom = sizeof(arrayU8WriteFrom) - 1; JSHandle handleEcmaStrU8WriteFrom(thread, EcmaString::CreateFromUtf8(ecmaVMPtr, &arrayU8WriteFrom[0], lengthEcmaStrU8WriteFrom, true)); size_t sizeEcmaStrU16WriteTo = 10; JSHandle handleEcmaStrU16WriteTo(thread, - EcmaString::AllocStringObject(ecmaVMPtr, sizeEcmaStrU16WriteTo, false)); + EcmaString::CreateLineString(ecmaVMPtr, sizeEcmaStrU16WriteTo, false)); uint32_t indexStartWriteFromU8ToU16 = 1; uint32_t numBytesWriteFromU8ToU16 = 4; handleEcmaStrU16WriteTo->WriteData(*handleEcmaStrU8WriteFrom, indexStartWriteFromU8ToU16, sizeEcmaStrU16WriteTo, @@ -753,17 +708,17 @@ HWTEST_F_L0(EcmaStringTest, WriteData_004) /* * @tc.name: WriteData_005 - * @tc.desc: Check whether the target EcmaString made by AllocStringObject( , false, ) changed through calling + * @tc.desc: Check whether the target EcmaString made by CreateLineString( , false, ) changed through calling * WriteData function with a source char is within expectations. * @tc.type: FUNC * @tc.require: */ HWTEST_F_L0(EcmaStringTest, WriteData_005) { - // WriteData(). From char to EcmaString made by AllocStringObject( , false, ). + // WriteData(). From char to EcmaString made by CreateLineString( , false, ). size_t sizeEcmaStrU16WriteTo = 10; JSHandle handleEcmaStrU16WriteTo(thread, - EcmaString::AllocStringObject(ecmaVMPtr, sizeEcmaStrU16WriteTo, false)); + EcmaString::CreateLineString(ecmaVMPtr, sizeEcmaStrU16WriteTo, false)); char u8Write = 'a'; uint32_t indexAt = 4; handleEcmaStrU16WriteTo->WriteData(u8Write, indexAt); @@ -795,31 +750,6 @@ HWTEST_F_L0(EcmaStringTest, GetUtf8Length) EXPECT_EQ(handleEcmaStrU16NotComp->GetUtf8Length(), 2 * lengthEcmaStrU16NotComp + 1); } -/* - * @tc.name: GetUtf16Length - * @tc.desc: Check whether the value returned through calling GetUtf16Length function is within expectations. - * @tc.type: FUNC - * @tc.require: - */ -HWTEST_F_L0(EcmaStringTest, GetUtf16Length) -{ - uint8_t arrayU8[6] = {3, 7, 19, 54, 99}; - uint16_t arrayU16Comp[] = {1, 12, 34, 56, 127}; - uint16_t arrayU16NotComp[] = {19, 54, 256, 11100, 65535}; - uint32_t lengthEcmaStrU8 = sizeof(arrayU8) - 1; - uint32_t lengthEcmaStrU16Comp = sizeof(arrayU16Comp) / sizeof(arrayU16Comp[0]); - uint32_t lengthEcmaStrU16NotComp = sizeof(arrayU16NotComp) / sizeof(arrayU16NotComp[0]); - JSHandle handleEcmaStrU8(thread, - EcmaString::CreateFromUtf8(ecmaVMPtr, &arrayU8[0], lengthEcmaStrU8, true)); - JSHandle handleEcmaStrU16Comp(thread, - EcmaString::CreateFromUtf16(ecmaVMPtr, &arrayU16Comp[0], lengthEcmaStrU16Comp, true)); - JSHandle handleEcmaStrU16NotComp(thread, - EcmaString::CreateFromUtf16(ecmaVMPtr, &arrayU16NotComp[0], lengthEcmaStrU16NotComp, false)); - EXPECT_EQ(handleEcmaStrU8->GetUtf16Length(), lengthEcmaStrU8); - EXPECT_EQ(handleEcmaStrU16Comp->GetUtf16Length(), lengthEcmaStrU16Comp); - EXPECT_EQ(handleEcmaStrU16NotComp->GetUtf16Length(), lengthEcmaStrU16NotComp); -} - /* * @tc.name: GetDataUtf8 * @tc.desc: Check whether the pointer returned through calling GetDataUtf8 function is within expectations. @@ -1631,17 +1561,17 @@ HWTEST_F_L0(EcmaStringTest, GetHashcode_004) /* * @tc.name: GetHashcode_005 - * @tc.desc: Check whether the value returned through an EcmaString made by AllocStringObject(, true/false, ) calling + * @tc.desc: Check whether the value returned through an EcmaString made by CreateLineString(, true/false, ) calling * GetHashcode function is within expectations. * @tc.type: FUNC * @tc.require: */ HWTEST_F_L0(EcmaStringTest, GetHashcode_005) { - // GetHashcode(). EcmaString made by AllocStringObject(). + // GetHashcode(). EcmaString made by CreateLineString(). size_t sizeAlloc = 5; - JSHandle handleEcmaStrAllocComp(thread, EcmaString::AllocStringObject(ecmaVMPtr, sizeAlloc, true)); - JSHandle handleEcmaStrAllocNotComp(thread, EcmaString::AllocStringObject(ecmaVMPtr, sizeAlloc, false)); + JSHandle handleEcmaStrAllocComp(thread, EcmaString::CreateLineString(ecmaVMPtr, sizeAlloc, true)); + JSHandle handleEcmaStrAllocNotComp(thread, EcmaString::CreateLineString(ecmaVMPtr, sizeAlloc, false)); EXPECT_EQ(handleEcmaStrAllocComp->GetHashcode(), 0U); EXPECT_EQ(handleEcmaStrAllocNotComp->GetHashcode(), 0U); } diff --git a/ecmascript/tests/js_api_lightweightset_test.cpp b/ecmascript/tests/js_api_lightweightset_test.cpp index 5d3a188e24..ff0abf6937 100644 --- a/ecmascript/tests/js_api_lightweightset_test.cpp +++ b/ecmascript/tests/js_api_lightweightset_test.cpp @@ -399,9 +399,8 @@ HWTEST_F_L0(JSAPILightWeightSetTest, ToString) JSHandle lws(thread, CreateLightWeightSet()); JSTaggedValue result1 = JSAPILightWeightSet::ToString(thread, lws); JSHandle resultHandle1(thread, result1); - [[maybe_unused]] auto *res1 = EcmaString::Cast(resultHandle1.GetTaggedValue().GetTaggedObject()); JSHandle det = thread->GetEcmaVM()->GetFactory()->NewFromASCII(""); - ASSERT_EQ(EcmaStringAccessor::Compare(res1, *det), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle1, det), 0); for (uint32_t i = 0; i < NODE_NUMBERS; i++) { value.Update(JSTaggedValue(i)); JSAPILightWeightSet::Add(thread, lws, value); @@ -409,8 +408,6 @@ HWTEST_F_L0(JSAPILightWeightSetTest, ToString) JSHandle str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0,1,2"); JSTaggedValue result = JSAPILightWeightSet::ToString(thread, lws); JSHandle resultHandle(thread, result); - [[maybe_unused]] auto *res = EcmaString::Cast(resultHandle.GetTaggedValue().GetTaggedObject()); - - ASSERT_EQ(EcmaStringAccessor::Compare(res, *str), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, str), 0); } } // namespace panda::test \ No newline at end of file diff --git a/ecmascript/tests/js_api_plain_array_test.cpp b/ecmascript/tests/js_api_plain_array_test.cpp index 984742910f..4c4d07d923 100644 --- a/ecmascript/tests/js_api_plain_array_test.cpp +++ b/ecmascript/tests/js_api_plain_array_test.cpp @@ -308,9 +308,8 @@ HWTEST_F_L0(JSAPIPlainArrayTest, PA_ToString) JSHandle array(thread, CreatePlainArray()); JSTaggedValue result1 = JSAPIPlainArray::ToString(thread, array); JSHandle resultHandle1(thread, result1); - [[maybe_unused]] auto *res1 = EcmaString::Cast(resultHandle1.GetTaggedValue().GetTaggedObject()); JSHandle det = thread->GetEcmaVM()->GetFactory()->NewFromASCII(""); - ASSERT_EQ(EcmaStringAccessor::Compare(res1, *det), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle1, det), 0); for (uint32_t i = 0; i < NODE_NUMBERS; i++) { uint32_t ikey = i; std::string ivalue = std::to_string(i); @@ -321,9 +320,8 @@ HWTEST_F_L0(JSAPIPlainArrayTest, PA_ToString) JSHandle str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0:0,1:1,2:2"); JSTaggedValue result = JSAPIPlainArray::ToString(thread, array); JSHandle resultHandle(thread, result); - [[maybe_unused]] auto *res = EcmaString::Cast(resultHandle.GetTaggedValue().GetTaggedObject()); - ASSERT_EQ(EcmaStringAccessor::Compare(res, *str), 0); + ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, str), 0); } /** diff --git a/ecmascript/tests/js_handle_test.cpp b/ecmascript/tests/js_handle_test.cpp index eb92aaf455..052e4bc0d2 100644 --- a/ecmascript/tests/js_handle_test.cpp +++ b/ecmascript/tests/js_handle_test.cpp @@ -65,8 +65,10 @@ HWTEST_F_L0(JSHandleTest, NewGlobalHandle) thread->GetEcmaVM()->CollectGarbage(TriggerGCType::FULL_GC); // check result - EXPECT_EQ(EcmaStringAccessor::Compare( - *factory->NewFromASCII("test1"), *reinterpret_cast(globalString)), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("test1"), + JSHandle(thread, *reinterpret_cast(globalString))), + 0); } HWTEST_F_L0(JSHandleTest, NewGlobalHandle1) @@ -91,15 +93,19 @@ HWTEST_F_L0(JSHandleTest, NewGlobalHandle1) // check result for (int i = 0; i <= 200; i++) { std::string test = "test" + std::to_string(i); - EXPECT_EQ(EcmaStringAccessor::Compare( - *factory->NewFromUtf8(test.c_str()), *reinterpret_cast(globalString[i])), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromUtf8(test.c_str()), + JSHandle(thread, *reinterpret_cast(globalString[i]))), + 0); } // trigger GC thread->GetEcmaVM()->CollectGarbage(TriggerGCType::FULL_GC); for (int i = 301; i < 600; i++) { std::string test = "test" + std::to_string(i); - EXPECT_EQ(EcmaStringAccessor::Compare( - *factory->NewFromUtf8(test.c_str()), *reinterpret_cast(globalString[i])), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromUtf8(test.c_str()), + JSHandle(thread, *reinterpret_cast(globalString[i]))), + 0); } } @@ -159,8 +165,10 @@ HWTEST_F_L0(JSHandleTest, DisposeAndNewGlobalHandle) // check result for (int i = 0; i <= 300; i++) { std::string test = "test" + std::to_string(i); - EXPECT_EQ(EcmaStringAccessor::Compare( - *factory->NewFromUtf8(test.c_str()), *reinterpret_cast(globalString[i])), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromUtf8(test.c_str()), + JSHandle(thread, *reinterpret_cast(globalString[i]))), + 0); } } @@ -180,8 +188,10 @@ HWTEST_F_L0(JSHandleTest, NewWeakGlobalHandle) thread->GetEcmaVM()->CollectGarbage(TriggerGCType::FULL_GC); // check result - EXPECT_EQ(EcmaStringAccessor::Compare( - *factory->NewFromASCII("test1"), *reinterpret_cast(globalString)), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromASCII("test1"), + JSHandle(thread, *reinterpret_cast(globalString))), + 0); EXPECT_TRUE(global->IsWeak(globalString)); } // trigger GC @@ -215,8 +225,10 @@ HWTEST_F_L0(JSHandleTest, NewWeakGlobalHandle1) // check result for (int i = 0; i <= 200; i++) { std::string test = "test" + std::to_string(i); - EXPECT_EQ(EcmaStringAccessor::Compare( - *factory->NewFromUtf8(test.c_str()), *reinterpret_cast(globalString[i])), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, + factory->NewFromUtf8(test.c_str()), + JSHandle(thread, *reinterpret_cast(globalString[i]))), + 0); } } // trigger GC diff --git a/ecmascript/tests/js_hclass_test.cpp b/ecmascript/tests/js_hclass_test.cpp index 92d436479b..fc5ed62bf7 100644 --- a/ecmascript/tests/js_hclass_test.cpp +++ b/ecmascript/tests/js_hclass_test.cpp @@ -85,9 +85,12 @@ HWTEST_F_L0(JSHClassTest, SizeFromJSHClass) objectSize = objectClass->SizeFromJSHClass(*objectClass); EXPECT_EQ(objectSize, 40U); #endif - objectClass = factory->NewEcmaHClass(EcmaString::SIZE, JSType::STRING, nullHandle); - objectSize = objectClass->SizeFromJSHClass(*objectClass); + EcmaString *string = factory->AllocLineStringObject(EcmaString::SIZE); + objectSize = string->GetClass()->SizeFromJSHClass(string); EXPECT_EQ(objectSize, 16U); + string = factory->AllocTreeStringObject(); + objectSize = string->GetClass()->SizeFromJSHClass(string); + EXPECT_EQ(objectSize, 32U); objectClass = factory->NewEcmaHClass(MachineCode::SIZE, JSType::MACHINE_CODE_OBJECT, nullHandle); objectSize = objectClass->SizeFromJSHClass(*objectClass); @@ -112,13 +115,15 @@ HWTEST_F_L0(JSHClassTest, HasReferenceField) ObjectFactory *factory = vm->GetFactory(); JSHandle nullHandle(thread, JSTaggedValue::Null()); - JSHandle obj1Class = factory->NewEcmaHClass(TaggedArray::SIZE, JSType::STRING, nullHandle); - JSHandle obj2Class = + JSHandle obj1Class = factory->NewEcmaHClass(TaggedArray::SIZE, JSType::LINE_STRING, nullHandle); + JSHandle obj2Class = factory->NewEcmaHClass(TaggedArray::SIZE, JSType::TREE_STRING, nullHandle); + JSHandle obj3Class = factory->NewEcmaHClass(TaggedArray::SIZE, JSType::JS_NATIVE_POINTER, nullHandle); - JSHandle obj3Class = factory->NewEcmaHClass(TaggedArray::SIZE, JSType::JS_OBJECT, nullHandle); + JSHandle obj4Class = factory->NewEcmaHClass(TaggedArray::SIZE, JSType::JS_OBJECT, nullHandle); EXPECT_FALSE(obj1Class->HasReferenceField()); - EXPECT_FALSE(obj2Class->HasReferenceField()); - EXPECT_TRUE(obj3Class->HasReferenceField()); + EXPECT_TRUE(obj2Class->HasReferenceField()); + EXPECT_FALSE(obj3Class->HasReferenceField()); + EXPECT_TRUE(obj4Class->HasReferenceField()); } HWTEST_F_L0(JSHClassTest, Clone) diff --git a/ecmascript/tests/js_locale_test.cpp b/ecmascript/tests/js_locale_test.cpp index e78cb03501..a3e7dfd454 100644 --- a/ecmascript/tests/js_locale_test.cpp +++ b/ecmascript/tests/js_locale_test.cpp @@ -228,7 +228,7 @@ HWTEST_F_L0(JSLocaleTest, CanonicalizeUnicodeLocaleId) canonicalizeLocaleId = JSLocale::CanonicalizeUnicodeLocaleId(thread, locale); JSHandle emptyString = factory->GetEmptyString(); - EXPECT_EQ(EcmaStringAccessor::Compare(*canonicalizeLocaleId, *emptyString), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, canonicalizeLocaleId, emptyString), 0); } /** diff --git a/ecmascript/tests/js_primitive_ref_test.cpp b/ecmascript/tests/js_primitive_ref_test.cpp index df43575847..f800021334 100644 --- a/ecmascript/tests/js_primitive_ref_test.cpp +++ b/ecmascript/tests/js_primitive_ref_test.cpp @@ -68,6 +68,6 @@ HWTEST_F_L0(JSPrimitiveRefTest, StringCreate) ASSERT_TRUE(status); JSHandle h = thread->GetEcmaVM()->GetFactory()->NewFromASCII("h"); JSHandle h2 = JSTaggedValue::ToString(thread, desc.GetValue()); - ASSERT_TRUE(EcmaStringAccessor::Compare(*h, *h2) == 0); + ASSERT_TRUE(EcmaStringAccessor::Compare(instance, h, h2) == 0); } } // namespace panda::test diff --git a/ecmascript/tests/js_regexp_iterator_test.cpp b/ecmascript/tests/js_regexp_iterator_test.cpp index 4175e3c950..80d5a9ac3f 100644 --- a/ecmascript/tests/js_regexp_iterator_test.cpp +++ b/ecmascript/tests/js_regexp_iterator_test.cpp @@ -127,7 +127,7 @@ HWTEST_F_L0(JSRegexpIteratorTest, Next) JSHandle matchResult = JSIterator::IteratorValue(thread, matchObj); JSHandle zeroHandle(JSObject::GetProperty(thread, matchResult, zero).GetValue()); JSHandle outputZero = JSTaggedValue::ToString(thread, zeroHandle); - EXPECT_EQ(EcmaStringAccessor::Compare(*outputZero, *compareVal), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, outputZero, compareVal), 0); EXPECT_FALSE(regExpIterator->GetDone()); } else { diff --git a/ecmascript/tests/tagged_tree_test.cpp b/ecmascript/tests/tagged_tree_test.cpp index 31f01f6c6b..506c8ac5be 100644 --- a/ecmascript/tests/tagged_tree_test.cpp +++ b/ecmascript/tests/tagged_tree_test.cpp @@ -69,9 +69,9 @@ public: JSHandle valueY = GetCallArg(argv, 1); if (valueX->IsString() && valueY->IsString()) { - auto xString = static_cast(valueX->GetTaggedObject()); - auto yString = static_cast(valueY->GetTaggedObject()); - int result = EcmaStringAccessor::Compare(xString, yString); + auto xHandle = JSHandle(valueX); + auto yHandle = JSHandle(valueY); + int result = EcmaStringAccessor::Compare(thread->GetEcmaVM(), xHandle, yHandle); if (result < 0) { return JSTaggedValue(1); } diff --git a/ecmascript/tests/tagged_value_test.cpp b/ecmascript/tests/tagged_value_test.cpp index 096ea4050d..14efa45958 100644 --- a/ecmascript/tests/tagged_value_test.cpp +++ b/ecmascript/tests/tagged_value_test.cpp @@ -866,16 +866,16 @@ HWTEST_F_L0(JSTaggedValueTest, ToObject) JSTaggedValue tagged4 = JSTaggedValue(JSHandle::Cast(JSTaggedValue::ToObject(thread, value4))->GetValue()); EXPECT_TRUE(tagged4.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(reinterpret_cast(tagged4.GetRawData()), - value4.GetObject()), 0); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, + JSHandle(thread, tagged4), JSHandle(value4)), 0); JSHandle symbol = factory->NewPublicSymbolWithChar("bbb"); JSHandle str = factory->NewFromASCII("bbb"); JSHandle value5(symbol); JSTaggedValue tagged5 = JSTaggedValue(JSHandle::Cast(JSTaggedValue::ToObject(thread, value5))->GetValue()); - EXPECT_EQ(EcmaStringAccessor::Compare(EcmaString::Cast( - reinterpret_cast(tagged5.GetRawData())->GetDescription().GetTaggedObject()), *str), + EXPECT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(thread, + EcmaString::Cast(reinterpret_cast(tagged5.GetRawData())->GetDescription())), str), 0); EXPECT_TRUE(tagged5.IsSymbol()); From 2b03d7027116b0dfe6fcb1a316189c8d1bac6345 Mon Sep 17 00:00:00 2001 From: huangzhenghua Date: Fri, 25 Nov 2022 15:22:42 +0800 Subject: [PATCH 06/14] clean alarm Signed-off-by: huangzhenghua Change-Id: Ibe52bcaec35aecbc9cdf56bd9d1734adb94b8b7b --- ecmascript/base/string_helper.h | 10 +++++----- ecmascript/base/typed_array_helper.cpp | 2 +- ecmascript/builtins/builtins_ark_tools.cpp | 1 + ecmascript/compiler/bytecode_circuit_builder.cpp | 2 +- ecmascript/compiler/gate_accessor.h | 2 ++ ecmascript/compiler/interpreter_stub-inl.h | 4 ---- ecmascript/compiler/stub_builder.h | 2 +- ecmascript/dfx/native_dfx/backtrace.cpp | 4 ---- ecmascript/snapshot/mem/snapshot_processor.cpp | 1 - ecmascript/tagged_list.cpp | 10 ++++------ ecmascript/tagged_list.h | 2 +- ecmascript/taskpool/task_queue.cpp | 1 - 12 files changed, 16 insertions(+), 25 deletions(-) diff --git a/ecmascript/base/string_helper.h b/ecmascript/base/string_helper.h index b712014076..d05b47de7e 100644 --- a/ecmascript/base/string_helper.h +++ b/ecmascript/base/string_helper.h @@ -261,31 +261,31 @@ public: if (srcStr.find('\n') == std::string::npos) { escape = false; } - int prePos = 0; + size_t prePos = 0; int findPrePos = lineNumber - 1; for (int i = 0; i < findPrePos; i++) { if (escape) { prePos = srcStr.find('\n', prePos); - if (prePos == -1) { + if (prePos == std::string::npos) { return ""; } prePos += 1; } else { prePos = srcStr.find("\\n", prePos); - if (prePos == -1) { + if (prePos == std::string::npos) { return ""; } // Add the two characters found to start searching again prePos += 2; } } - int findEndPos = 0; + size_t findEndPos = 0; if (escape) { findEndPos = srcStr.find('\n', prePos); } else { findEndPos = srcStr.find("\\n", prePos); } - if (findEndPos == -1) { + if (findEndPos == std::string::npos) { return srcStr.substr(prePos, srcStr.length() - prePos); } ASSERT(findEndPos > prePos); diff --git a/ecmascript/base/typed_array_helper.cpp b/ecmascript/base/typed_array_helper.cpp index d0a4d55dec..562e4a4980 100644 --- a/ecmascript/base/typed_array_helper.cpp +++ b/ecmascript/base/typed_array_helper.cpp @@ -425,7 +425,7 @@ JSHandle TypedArrayHelper::AllocateTypedArrayBuffer(JSThread *thread, uint32_t elementSize = TypedArrayHelper::GetSizeFromType(arrayType); // 6. Let byteLength be elementSize × length. uint32_t arrayLength = static_cast(length); - uint64_t byteLength = elementSize * arrayLength; + uint64_t byteLength = static_cast(elementSize) * length; // 7. Let data be ? AllocateArrayBuffer(%ArrayBuffer%, byteLength). JSTaggedValue data; if (byteLength > JSTypedArray::MAX_ONHEAP_LENGTH) { diff --git a/ecmascript/builtins/builtins_ark_tools.cpp b/ecmascript/builtins/builtins_ark_tools.cpp index cf2d6c3816..0b70fa2345 100644 --- a/ecmascript/builtins/builtins_ark_tools.cpp +++ b/ecmascript/builtins/builtins_ark_tools.cpp @@ -163,6 +163,7 @@ bool BuiltinsArkTools::CreateFile(std::string &fileName) LOG_ECMA(ERROR) << "file create failed, errno = "<< errno; return false; } + close(fd); return true; } else { fileName = path; diff --git a/ecmascript/compiler/bytecode_circuit_builder.cpp b/ecmascript/compiler/bytecode_circuit_builder.cpp index 03ccb92036..2ceb5a8029 100644 --- a/ecmascript/compiler/bytecode_circuit_builder.cpp +++ b/ecmascript/compiler/bytecode_circuit_builder.cpp @@ -56,7 +56,7 @@ void BytecodeCircuitBuilder::CollectRegionInfo(uint32_t bcIndex) { auto pc = pcOffsets_[bcIndex]; auto &info = infoData_[bcIndex]; - int32_t offset; + int32_t offset = 0; if (info.IsJump()) { switch (info.GetOpcode()) { case EcmaOpcode::JEQZ_IMM8: diff --git a/ecmascript/compiler/gate_accessor.h b/ecmascript/compiler/gate_accessor.h index db964e3ba2..b0c6957d81 100644 --- a/ecmascript/compiler/gate_accessor.h +++ b/ecmascript/compiler/gate_accessor.h @@ -37,6 +37,7 @@ public: const ConstUseIterator operator++() { + ASSERT(out_ != nullptr); if (!out_->IsNextOutNull()) { out_ = out_->GetNextOutConst(); return *this; @@ -93,6 +94,7 @@ public: const UseIterator& operator++() { + ASSERT(out_ != nullptr); out_ = out_->IsNextOutNull() ? nullptr : out_->GetNextOut(); return *this; diff --git a/ecmascript/compiler/interpreter_stub-inl.h b/ecmascript/compiler/interpreter_stub-inl.h index 25401ff7ab..7a3102c89e 100644 --- a/ecmascript/compiler/interpreter_stub-inl.h +++ b/ecmascript/compiler/interpreter_stub-inl.h @@ -692,7 +692,6 @@ GateRef InterpreterToolsStubBuilder::GetStringId(const StringIdInfo &info) if (info.length == StringIdInfo::Length::BITS_16) { stringId = ZExtInt16ToInt32(ReadInst16_0(info.pc)); } else { - stringId = 0; std::abort(); } break; @@ -703,7 +702,6 @@ GateRef InterpreterToolsStubBuilder::GetStringId(const StringIdInfo &info) } else if (info.length == StringIdInfo::Length::BITS_32) { stringId = ReadInst32_1(info.pc); } else { - stringId = 0; std::abort(); } break; @@ -712,13 +710,11 @@ GateRef InterpreterToolsStubBuilder::GetStringId(const StringIdInfo &info) if (info.length == StringIdInfo::Length::BITS_16) { stringId = ZExtInt16ToInt32(ReadInst16_2(info.pc)); } else { - stringId = 0; std::abort(); } break; } default: { - stringId = 0; std::abort(); break; } diff --git a/ecmascript/compiler/stub_builder.h b/ecmascript/compiler/stub_builder.h index 3de54b2858..3b2eace1b6 100644 --- a/ecmascript/compiler/stub_builder.h +++ b/ecmascript/compiler/stub_builder.h @@ -531,7 +531,7 @@ private: GateRef FastBinaryOp(GateRef left, GateRef right, const BinaryOperation& intOp, const BinaryOperation& floatOp); void InitializeArguments(); - CallSignature *callSignature_; + CallSignature *callSignature_ {nullptr}; Environment *env_; }; } // namespace panda::ecmascript::kungfu diff --git a/ecmascript/dfx/native_dfx/backtrace.cpp b/ecmascript/dfx/native_dfx/backtrace.cpp index 5bc597bfca..c9cc69e461 100644 --- a/ecmascript/dfx/native_dfx/backtrace.cpp +++ b/ecmascript/dfx/native_dfx/backtrace.cpp @@ -56,13 +56,9 @@ void PrintBacktrace(uintptr_t value) std::ostringstream stack; for (int i = 1; i < level; i++) { const char *file = ""; - const char *symbol = ""; uintptr_t offset = 0; Dl_info info; if (dladdr(buffer[i], &info)) { - if (info.dli_sname) { - symbol = info.dli_sname; - } if (info.dli_fname) { file = info.dli_fname; } diff --git a/ecmascript/snapshot/mem/snapshot_processor.cpp b/ecmascript/snapshot/mem/snapshot_processor.cpp index 28cd91a769..ef8b1d1bfc 100644 --- a/ecmascript/snapshot/mem/snapshot_processor.cpp +++ b/ecmascript/snapshot/mem/snapshot_processor.cpp @@ -1228,7 +1228,6 @@ void SnapshotProcessor::DeserializeSpaceObject(uintptr_t beginAddr, Space* space } else { liveObjectSize = fileRegion->AliveObject(); size_t freeObjSize = region->end_ - region->packedData_.begin_ - liveObjectSize; - ASSERT(freeObjSize >= 0); // if region remain 8 bytes which is added to wasted, // we should subtract it when calculate region index if (freeObjSize < Constants::FREE_OBJECT_MIN_SIZE) { diff --git a/ecmascript/tagged_list.cpp b/ecmascript/tagged_list.cpp index 1e9c04dcfd..c49499df22 100644 --- a/ecmascript/tagged_list.cpp +++ b/ecmascript/tagged_list.cpp @@ -192,7 +192,7 @@ int TaggedList::FindDataIndexByNodeIndex(int index) const } template -void TaggedList::MapNodeIndexToDataIndex(int* nodeIndexMapToDataIndex, int length) +void TaggedList::MapNodeIndexToDataIndex(std::vector &nodeIndexMapToDataIndex, int length) { int i = 0; int nextIndex = ELEMENTS_START_INDEX; @@ -404,13 +404,13 @@ JSTaggedValue TaggedSingleList::ReplaceAllElements(JSThread *thread, const JSHan JSTaggedValue TaggedSingleList::Sort(JSThread *thread, const JSHandle &callbackFn, const JSHandle &taggedList) { - int length = taggedList->NumberOfNodes(); + const int length = taggedList->NumberOfNodes(); ASSERT(length > 0); JSMutableHandle presentValue(thread, JSTaggedValue::Undefined()); JSMutableHandle middleValue(thread, JSTaggedValue::Undefined()); JSMutableHandle previousValue(thread, JSTaggedValue::Undefined()); // create index map - int* nodeIndexMapToDataIndex = new int[length]; + std::vector nodeIndexMapToDataIndex(length, 0); taggedList->MapNodeIndexToDataIndex(nodeIndexMapToDataIndex, length); int beginIndex = 0; @@ -442,7 +442,6 @@ JSTaggedValue TaggedSingleList::Sort(JSThread *thread, const JSHandle TaggedDoubleList::GetByDataIndex(const int dataInd int TaggedDoubleList::GetPrevNode(const int index) { - int prevDataIndex = 0; int len = NumberOfNodes(); // When index < (len / 2), search doubleList from the beginning if ((len / 2) > index) { @@ -612,7 +610,7 @@ int TaggedDoubleList::GetPrevNode(const int index) int leftNodeLen = len - 1 - index; // When insert at last if (leftNodeLen == -1) { - return prevDataIndex = GetElement(TAIL_TABLE_INDEX).GetInt(); + return GetElement(TAIL_TABLE_INDEX).GetInt(); } // when index >= (len / 2), search doubleList from the end return FindPrevNodeByIndexAtLast(leftNodeLen); diff --git a/ecmascript/tagged_list.h b/ecmascript/tagged_list.h index 104572e96d..8bd534bc16 100644 --- a/ecmascript/tagged_list.h +++ b/ecmascript/tagged_list.h @@ -48,7 +48,7 @@ public: int FindIndexByElement(const JSTaggedValue &element); int FindLastIndexByElement(const JSTaggedValue &element); int FindDataIndexByNodeIndex(int index) const; - void MapNodeIndexToDataIndex(int* nodeIndexMapToDataIndex, int length); + void MapNodeIndexToDataIndex(std::vector &nodeIndexMapToDataIndex, int length); void RemoveNode(JSThread *thread, int prevDataIndex); int FindPrevNodeByIndex(int index) const; int FindPrevNodeByValue(const JSTaggedValue &element); diff --git a/ecmascript/taskpool/task_queue.cpp b/ecmascript/taskpool/task_queue.cpp index 4c186650d8..22a1bbc1e0 100644 --- a/ecmascript/taskpool/task_queue.cpp +++ b/ecmascript/taskpool/task_queue.cpp @@ -49,7 +49,6 @@ void TaskQueue::TerminateTask(int32_t id, TaskType type) continue; } if (type != TaskType::ALL && type != (*iter)->GetTaskType()) { - iter++; continue; } (*iter)->Terminated(); From ac5f1fd688d63a3aab2d772c8798e3e643e3eaa7 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Fri, 25 Nov 2022 16:51:55 +0800 Subject: [PATCH 07/14] clean code Signed-off-by: songzhengchao Change-Id: Idfc4ea5c931e99b6008da3f24758d6411b0f88f3 --- BUILD.gn | 4 +-- ecmascript/aot_file_manager.cpp | 4 +-- ecmascript/ark_stackmap_parser.cpp | 2 +- ecmascript/compiler/aot_compiler.cpp | 4 +-- ecmascript/compiler/circuit_builder.h | 10 +++---- ecmascript/compiler/compiler_log.cpp | 4 +-- ecmascript/compiler/compiler_log.h | 8 +++--- ecmascript/compiler/llvm_ir_builder.cpp | 2 +- ecmascript/compiler/pass_manager.cpp | 2 +- ecmascript/compiler/slowpath_lowering.cpp | 2 +- ecmascript/compiler/slowpath_lowering.h | 8 +++--- .../trampoline/aarch64/optimized_call.cpp | 2 +- .../trampoline/x64/optimized_call.cpp | 2 +- ecmascript/compiler/type_lowering.cpp | 2 +- ecmascript/deoptimizer/calleeReg.h | 7 +++-- ecmascript/{ => deoptimizer}/deoptimizer.cpp | 2 +- ecmascript/{ => deoptimizer}/deoptimizer.h | 11 ++++---- ecmascript/{ => deoptimizer}/relocator.cpp | 2 +- ecmascript/{ => deoptimizer}/relocator.h | 6 ++-- ecmascript/js_runtime_options.cpp | 16 +++++------ ecmascript/js_runtime_options.h | 28 +++++++++---------- ecmascript/stubs/runtime_stubs.cpp | 2 +- 22 files changed, 66 insertions(+), 64 deletions(-) rename ecmascript/{ => deoptimizer}/deoptimizer.cpp (99%) rename ecmascript/{ => deoptimizer}/deoptimizer.h (95%) rename ecmascript/{ => deoptimizer}/relocator.cpp (99%) rename ecmascript/{ => deoptimizer}/relocator.h (94%) diff --git a/BUILD.gn b/BUILD.gn index 8c3b8767f7..07efc3fe26 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -454,15 +454,15 @@ ecma_source = [ "ecmascript/containers/containers_treeset.cpp", "ecmascript/containers/containers_vector.cpp", "ecmascript/deoptimizer/calleeReg.cpp", + "ecmascript/deoptimizer/deoptimizer.cpp", + "ecmascript/deoptimizer/relocator.cpp", "ecmascript/dfx/pgo_profiler/pgo_profiler_loader.cpp", "ecmascript/dfx/pgo_profiler/pgo_profiler_manager.cpp", "ecmascript/dfx/stackinfo/js_stackinfo.cpp", - "ecmascript/deoptimizer.cpp", "ecmascript/dfx/vmstat/caller_stat.cpp", "ecmascript/dfx/vmstat/runtime_stat.cpp", "ecmascript/dfx/vm_thread_control.cpp", "ecmascript/dump.cpp", - "ecmascript/relocator.cpp", "ecmascript/ecma_string.cpp", "ecmascript/ecma_string_table.cpp", "ecmascript/ecma_vm.cpp", diff --git a/ecmascript/aot_file_manager.cpp b/ecmascript/aot_file_manager.cpp index 66835e6ac0..5e31384bfc 100644 --- a/ecmascript/aot_file_manager.cpp +++ b/ecmascript/aot_file_manager.cpp @@ -22,8 +22,8 @@ #include "ecmascript/base/config.h" #include "ecmascript/compiler/bc_call_signature.h" #include "ecmascript/compiler/common_stubs.h" -#include "ecmascript/deoptimizer.h" -#include "ecmascript/relocator.h" +#include "ecmascript/deoptimizer/deoptimizer.h" +#include "ecmascript/deoptimizer/relocator.h" #include "ecmascript/llvm_stackmap_parser.h" #include "ecmascript/ecma_vm.h" #include "ecmascript/message_string.h" diff --git a/ecmascript/ark_stackmap_parser.cpp b/ecmascript/ark_stackmap_parser.cpp index 162f156f1d..363828b317 100644 --- a/ecmascript/ark_stackmap_parser.cpp +++ b/ecmascript/ark_stackmap_parser.cpp @@ -15,7 +15,7 @@ #include "ecmascript/ark_stackmap_parser.h" #include "ecmascript/ark_stackmap_builder.h" #include "ecmascript/compiler/assembler/assembler.h" -#include "ecmascript/deoptimizer.h" +#include "ecmascript/deoptimizer/deoptimizer.h" #include "ecmascript/aot_file_manager.h" namespace panda::ecmascript::kungfu { diff --git a/ecmascript/compiler/aot_compiler.cpp b/ecmascript/compiler/aot_compiler.cpp index fa351f5020..5e0ad1567c 100644 --- a/ecmascript/compiler/aot_compiler.cpp +++ b/ecmascript/compiler/aot_compiler.cpp @@ -87,7 +87,7 @@ int Main(const int argc, const char **argv) std::string logOption = runtimeOptions.GetCompilerLogOption(); std::string logMethodsList = runtimeOptions.GetMethodsListForLog(); bool compilerLogTime = runtimeOptions.IsEnableCompilerLogTime(); - bool isEnableBcTrace = runtimeOptions.IsEnableByteCodeTrace(); + bool isTraceBC = runtimeOptions.IsTraceBC(); size_t maxAotMethodSize = runtimeOptions.GetMaxAotMethodSize(); bool isEnableTypeLowering = runtimeOptions.IsEnableTypeLowering(); uint32_t hotnessThreshold = runtimeOptions.GetPGOHotnessThreshold(); @@ -95,7 +95,7 @@ int Main(const int argc, const char **argv) CommonStubCSigns::Initialize(); RuntimeStubCSigns::Initialize(); - CompilerLog log(logOption, isEnableBcTrace); + CompilerLog log(logOption, isTraceBC); log.SetEnableCompilerLogTime(compilerLogTime); AotMethodLogList logList(logMethodsList); AOTFileGenerator generator(&log, &logList, vm); diff --git a/ecmascript/compiler/circuit_builder.h b/ecmascript/compiler/circuit_builder.h index 36c03b7393..cc0cf5c3c2 100644 --- a/ecmascript/compiler/circuit_builder.h +++ b/ecmascript/compiler/circuit_builder.h @@ -134,8 +134,8 @@ public: TRIPLE_ARM32, }; - CompilationConfig(const std::string &triple, bool enablePGOProfiler = false, bool isEnableBcTrace = false) - : triple_(GetTripleFromString(triple)), isEnableBcTrace_(isEnableBcTrace), enablePGOProfiler_(enablePGOProfiler) + CompilationConfig(const std::string &triple, bool enablePGOProfiler = false, bool isTraceBC = false) + : triple_(GetTripleFromString(triple)), isTraceBc_(isTraceBC), enablePGOProfiler_(enablePGOProfiler) { } ~CompilationConfig() = default; @@ -165,9 +165,9 @@ public: return triple_; } - bool IsEnableByteCodeTrace() const + bool IsTraceBC() const { - return isEnableBcTrace_; + return isTraceBc_; } bool IsEnablePGOProfiler() const @@ -192,7 +192,7 @@ private: UNREACHABLE(); } Triple triple_; - bool isEnableBcTrace_; + bool isTraceBc_; bool enablePGOProfiler_; }; diff --git a/ecmascript/compiler/compiler_log.cpp b/ecmascript/compiler/compiler_log.cpp index 305ba6c7ca..11fb79a356 100644 --- a/ecmascript/compiler/compiler_log.cpp +++ b/ecmascript/compiler/compiler_log.cpp @@ -16,7 +16,7 @@ #include "ecmascript/compiler/compiler_log.h" namespace panda::ecmascript::kungfu { -CompilerLog::CompilerLog(const std::string &logOpt, bool enableBCTrace) +CompilerLog::CompilerLog(const std::string &logOpt, bool TraceBC) { outputCIR_ = logOpt.find("cir") != std::string::npos || logOpt.find("0") != std::string::npos; @@ -31,7 +31,7 @@ CompilerLog::CompilerLog(const std::string &logOpt, bool enableBCTrace) logOpt.find("cer") != std::string::npos; noneMethod_ = logOpt.find("all") == std::string::npos && logOpt.find("cer") == std::string::npos; - enableBCTrace_ = enableBCTrace; + traceBc_ = TraceBC; } bool MethodLogList::IncludesMethod(const std::string &methodName) const diff --git a/ecmascript/compiler/compiler_log.h b/ecmascript/compiler/compiler_log.h index 52a1b3f33e..6252e96522 100644 --- a/ecmascript/compiler/compiler_log.h +++ b/ecmascript/compiler/compiler_log.h @@ -30,7 +30,7 @@ namespace panda::ecmascript::kungfu { class CompilerLog { public: - explicit CompilerLog(const std::string &logOpt, bool enableBCTrace = false); + explicit CompilerLog(const std::string &logOpt, bool TraceBC = false); ~CompilerLog() = default; bool AllMethod() const @@ -68,9 +68,9 @@ public: return outputType_; } - bool IsEnableByteCodeTrace() const + bool IsTraceBC() const { - return enableBCTrace_; + return traceBc_; } bool GetEnableCompilerLogTime() const @@ -120,7 +120,7 @@ private: bool outputLLIR_ {false}; bool outputASM_ {false}; bool outputType_ {false}; - bool enableBCTrace_ {false}; + bool traceBc_ {false}; bool compilerLogTime_ {true}; bool enableMethodLog_ {false}; std::map timePassMap_ {}; diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index 9a0bd78fc9..0dc1baf959 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -22,7 +22,7 @@ #include "ecmascript/compiler/common_stubs.h" #include "ecmascript/compiler/gate.h" #include "ecmascript/compiler/rt_call_signature.h" -#include "ecmascript/deoptimizer.h" +#include "ecmascript/deoptimizer/deoptimizer.h" #include "ecmascript/frames.h" #include "ecmascript/js_thread.h" #include "ecmascript/method.h" diff --git a/ecmascript/compiler/pass_manager.cpp b/ecmascript/compiler/pass_manager.cpp index 20afc16b80..3ef6326893 100644 --- a/ecmascript/compiler/pass_manager.cpp +++ b/ecmascript/compiler/pass_manager.cpp @@ -41,7 +41,7 @@ bool PassManager::Compile(const std::string &fileName, AOTFileGenerator &generat auto aotModuleAssembler = new LLVMAssembler(aotModule->GetModule(), LOptions(optLevel_, true, relocMode_)); - CompilationConfig cmpCfg(triple_, false, log_->IsEnableByteCodeTrace()); + CompilationConfig cmpCfg(triple_, false, log_->IsTraceBC()); Bytecodes bytecodes; auto &bytecodeInfo = bcInfoCollector.GetBytecodeInfo(); auto lexEnvManager = LexEnvManager(bytecodeInfo); diff --git a/ecmascript/compiler/slowpath_lowering.cpp b/ecmascript/compiler/slowpath_lowering.cpp index ea748c6970..ace7835ae9 100644 --- a/ecmascript/compiler/slowpath_lowering.cpp +++ b/ecmascript/compiler/slowpath_lowering.cpp @@ -3381,7 +3381,7 @@ void SlowPathLowering::LowerWideStPatchVar(GateRef gate, GateRef glue) void SlowPathLowering::DebugPrintBC(GateRef gate, GateRef glue) { - if (enableBcTrace_) { + if (traceBc_) { EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate); auto ecmaOpcodeGate = builder_.Int32(static_cast(ecmaOpcode)); GateRef constOpcode = builder_.ToTaggedInt(builder_.ZExtInt32ToInt64(ecmaOpcodeGate)); diff --git a/ecmascript/compiler/slowpath_lowering.h b/ecmascript/compiler/slowpath_lowering.h index f819cd8514..e32cc6c952 100644 --- a/ecmascript/compiler/slowpath_lowering.h +++ b/ecmascript/compiler/slowpath_lowering.h @@ -119,7 +119,7 @@ public: dependEntry_(Circuit::GetCircuitRoot(OpCode(OpCode::DEPEND_ENTRY))), enableLog_(enableLog), methodName_(name) { - enableBcTrace_ = cmpCfg->IsEnableByteCodeTrace(); + traceBc_ = cmpCfg->IsTraceBC(); } ~SlowPathLowering() = default; void CallRuntimeLowering(); @@ -129,9 +129,9 @@ public: return enableLog_; } - bool IsEnableByteCodeTrace() const + bool IsTraceBC() const { - return enableBcTrace_; + return traceBc_; } private: @@ -300,7 +300,7 @@ private: CircuitBuilder builder_; GateRef dependEntry_; bool enableLog_ {false}; - bool enableBcTrace_ {false}; + bool traceBc_ {false}; std::string methodName_; }; } // panda::ecmascript::kungfu diff --git a/ecmascript/compiler/trampoline/aarch64/optimized_call.cpp b/ecmascript/compiler/trampoline/aarch64/optimized_call.cpp index 2b905f09a3..eb1920947d 100644 --- a/ecmascript/compiler/trampoline/aarch64/optimized_call.cpp +++ b/ecmascript/compiler/trampoline/aarch64/optimized_call.cpp @@ -19,7 +19,7 @@ #include "ecmascript/compiler/argument_accessor.h" #include "ecmascript/compiler/common_stubs.h" #include "ecmascript/compiler/rt_call_signature.h" -#include "ecmascript/deoptimizer.h" +#include "ecmascript/deoptimizer/deoptimizer.h" #include "ecmascript/ecma_runtime_call_info.h" #include "ecmascript/frames.h" #include "ecmascript/js_function.h" diff --git a/ecmascript/compiler/trampoline/x64/optimized_call.cpp b/ecmascript/compiler/trampoline/x64/optimized_call.cpp index 354291de45..a0502d1b66 100644 --- a/ecmascript/compiler/trampoline/x64/optimized_call.cpp +++ b/ecmascript/compiler/trampoline/x64/optimized_call.cpp @@ -19,7 +19,7 @@ #include "ecmascript/compiler/common_stubs.h" #include "ecmascript/compiler/rt_call_signature.h" #include "ecmascript/compiler/argument_accessor.h" -#include "ecmascript/deoptimizer.h" +#include "ecmascript/deoptimizer/deoptimizer.h" #include "ecmascript/ecma_runtime_call_info.h" #include "ecmascript/frames.h" #include "ecmascript/js_function.h" diff --git a/ecmascript/compiler/type_lowering.cpp b/ecmascript/compiler/type_lowering.cpp index 81afe66ec3..194a7caf19 100644 --- a/ecmascript/compiler/type_lowering.cpp +++ b/ecmascript/compiler/type_lowering.cpp @@ -15,7 +15,7 @@ #include "ecmascript/compiler/builtins_lowering.h" #include "ecmascript/compiler/type_lowering.h" -#include "ecmascript/deoptimizer.h" +#include "ecmascript/deoptimizer/deoptimizer.h" #include "ecmascript/js_arraybuffer.h" #include "ecmascript/js_native_pointer.h" diff --git a/ecmascript/deoptimizer/calleeReg.h b/ecmascript/deoptimizer/calleeReg.h index 19f7ee3293..0eb42bb2bc 100644 --- a/ecmascript/deoptimizer/calleeReg.h +++ b/ecmascript/deoptimizer/calleeReg.h @@ -13,8 +13,9 @@ * limitations under the License. */ -#ifndef ECMASCRIPT_COMPILER_CALLEE_REG_H -#define ECMASCRIPT_COMPILER_CALLEE_REG_H +#ifndef ECMASCRIPT_DEOPTIMIZER_CALLEE_REG_H +#define ECMASCRIPT_DEOPTIMIZER_CALLEE_REG_H + #include #include "ecmascript/common.h" #include "ecmascript/llvm_stackmap_type.h" @@ -67,4 +68,4 @@ private: std::map reg2Location_; }; } // namespace panda::ecmascript -#endif // ECMASCRIPT_COMPILER_CALLEE_REG_H +#endif // ECMASCRIPT_DEOPTIMIZER_CALLEE_REG_H diff --git a/ecmascript/deoptimizer.cpp b/ecmascript/deoptimizer/deoptimizer.cpp similarity index 99% rename from ecmascript/deoptimizer.cpp rename to ecmascript/deoptimizer/deoptimizer.cpp index 148ed62b23..aed09291ca 100644 --- a/ecmascript/deoptimizer.cpp +++ b/ecmascript/deoptimizer/deoptimizer.cpp @@ -229,7 +229,7 @@ bool Deoptimizier::CollectVirtualRegisters(Method* method, FrameWriter *frameWri void Deoptimizier::Dump(Method* method) { - if (enableDeoptTrace_) { + if (traceDeopt_) { std::string data = JsStackInfo::BuildMethodTrace(method, pc_); LOG_COMPILER(INFO) << "Deoptimize" << data; const uint8_t *pc = method->GetBytecodeArray() + pc_; diff --git a/ecmascript/deoptimizer.h b/ecmascript/deoptimizer/deoptimizer.h similarity index 95% rename from ecmascript/deoptimizer.h rename to ecmascript/deoptimizer/deoptimizer.h index aca3a6be8d..e340f89d56 100644 --- a/ecmascript/deoptimizer.h +++ b/ecmascript/deoptimizer/deoptimizer.h @@ -13,8 +13,9 @@ * limitations under the License. */ -#ifndef ECMASCRIPT_DEOPTIMIZER_H -#define ECMASCRIPT_DEOPTIMIZER_H +#ifndef ECMASCRIPT_DEOPTIMIZER_DEOPTIMIZER_H +#define ECMASCRIPT_DEOPTIMIZER_DEOPTIMIZER_H + #include "ecmascript/base/aligned_struct.h" #include "ecmascript/compiler/argument_accessor.h" #include "ecmascript/deoptimizer/calleeReg.h" @@ -93,7 +94,7 @@ public: kungfu::CalleeReg callreg; numCalleeRegs_ = static_cast(callreg.GetCallRegNum()); JSRuntimeOptions options = thread_->GetEcmaVM()->GetJSOptions(); - enableDeoptTrace_ = options.IsEnableDeoptTrace(); + traceDeopt_= options.GetTraceDeopt(); } void CollectVregs(const std::vector& deoptBundle); void CollectDeoptBundleVec(std::vector& deoptBundle); @@ -150,8 +151,8 @@ private: JSTaggedValue env_ {JSTaggedValue::Undefined()}; size_t frameArgc_ {0}; JSTaggedType *frameArgvs_ {nullptr}; - bool enableDeoptTrace_ {false}; + bool traceDeopt_{false}; }; } // namespace panda::ecmascript -#endif // ECMASCRIPT_DEOPTIMIZER_H \ No newline at end of file +#endif // ECMASCRIPT_DEOPTIMIZER_DEOPTIMIZER_H \ No newline at end of file diff --git a/ecmascript/relocator.cpp b/ecmascript/deoptimizer/relocator.cpp similarity index 99% rename from ecmascript/relocator.cpp rename to ecmascript/deoptimizer/relocator.cpp index 2da38361ba..db81312e1a 100644 --- a/ecmascript/relocator.cpp +++ b/ecmascript/deoptimizer/relocator.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "ecmascript/relocator.h" +#include "ecmascript/deoptimizer/relocator.h" #include #include #include "ecmascript/compiler/assembler/aarch64/assembler_aarch64_constants.h" diff --git a/ecmascript/relocator.h b/ecmascript/deoptimizer/relocator.h similarity index 94% rename from ecmascript/relocator.h rename to ecmascript/deoptimizer/relocator.h index f13fa42c83..1b7e4a41bc 100644 --- a/ecmascript/relocator.h +++ b/ecmascript/deoptimizer/relocator.h @@ -13,8 +13,8 @@ * limitations under the License. */ -#ifndef ECMASCRIPT_RELCATOR_H -#define ECMASCRIPT_RELCATOR_H +#ifndef ECMASCRIPT_DEOPTIMIZER_RELCATOR_H +#define ECMASCRIPT_DEOPTIMIZER_RELCATOR_H #include "ecmascript/common.h" #if !WIN_OR_MAC_OR_IOS_PLATFORM @@ -80,5 +80,5 @@ private: }; } // panda::ecmascript #endif -#endif // ECMASCRIPT_RELCATOR_H +#endif // ECMASCRIPT_DEOPTIMIZER_RELCATOR_H diff --git a/ecmascript/js_runtime_options.cpp b/ecmascript/js_runtime_options.cpp index cb684e074e..8f3fa255e7 100644 --- a/ecmascript/js_runtime_options.cpp +++ b/ecmascript/js_runtime_options.cpp @@ -56,8 +56,8 @@ const std::string PUBLIC_API HELP_OPTION_MSG = "--compiler-log-snapshot: Enable to print snapshot information. Default: false\n" "--compiler-log-time: Enable to print pass compiler time. Default: false\n" "--enable-ark-tools: Enable ark tools to debug. Default: false\n" - "--enable-bytecode-trace: enable tracing bytecode for aot runtime. Default: false\n" - "--enable-deopt-trace: enable tracing deopt for aot runtime. Default: false\n" + "--trace-bc: enable tracing bytecode for aot runtime. Default: false\n" + "--trace-deopt: enable tracing deopt for aot runtime. Default: false\n" "--enable-cpuprofiler: Enable cpuprofiler to sample call stack and output to json file. Default: false\n" "--enable-force-gc: enable force gc when allocating object. Default: true\n" "--enable-ic: switch of inline cache. Default: true\n" @@ -124,8 +124,8 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv) {"compiler-log-snapshot", required_argument, nullptr, OPTION_COMPILER_LOG_SNAPSHOT}, {"compiler-log-time", required_argument, nullptr, OPTION_COMPILER_LOG_TIME}, {"enable-ark-tools", required_argument, nullptr, OPTION_ENABLE_ARK_TOOLS}, - {"enable-bytecode-trace", required_argument, nullptr, OPTION_ENABLE_BC_TRACE}, - {"enable-deopt-trace", required_argument, nullptr, OPTION_ENABLE_DEOPT_TRACE}, + {"trace-bc", required_argument, nullptr, OPTION_TRACE_BC}, + {"trace-deopt", required_argument, nullptr, OPTION_TRACE_DEOPT}, {"enable-cpuprofiler", required_argument, nullptr, OPTION_ENABLE_CPUPROFILER}, {"enable-force-gc", required_argument, nullptr, OPTION_ENABLE_FORCE_GC}, {"enable-ic", required_argument, nullptr, OPTION_ENABLE_IC}, @@ -264,18 +264,18 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv) return false; } break; - case OPTION_ENABLE_BC_TRACE: + case OPTION_TRACE_BC: ret = ParseBoolParam(&argBool); if (ret) { - SetEnableByteCodeTrace(argBool); + SetTraceBc(argBool); } else { return false; } break; - case OPTION_ENABLE_DEOPT_TRACE: + case OPTION_TRACE_DEOPT: ret = ParseBoolParam(&argBool); if (ret) { - SetEnableDeoptTrace(argBool); + SetTraceDeopt(argBool); } else { return false; } diff --git a/ecmascript/js_runtime_options.h b/ecmascript/js_runtime_options.h index 658f01f2fa..3835622a1e 100644 --- a/ecmascript/js_runtime_options.h +++ b/ecmascript/js_runtime_options.h @@ -86,8 +86,8 @@ enum CommandValues { OPTION_COMPILER_LOG_TIME, OPTION_IS_WORKER, OPTION_BUILTINS_DTS, - OPTION_ENABLE_BC_TRACE, - OPTION_ENABLE_DEOPT_TRACE, + OPTION_TRACE_BC, + OPTION_TRACE_DEOPT, OPTION_LOG_LEVEL, OPTION_LOG_DEBUG, OPTION_LOG_INFO, @@ -601,19 +601,19 @@ public: return builtinsDTS_; } - void SetEnableByteCodeTrace(bool value) + void SetTraceBc(bool value) { - enablebcTrace_ = value; + traceBc_ = value; } - bool IsEnableByteCodeTrace() const + bool IsTraceBC() const { - return enablebcTrace_; + return traceBc_; } - bool WasSetEnableByteCodeTrace() const + bool WasSetTraceBc() const { - return WasOptionSet(OPTION_ENABLE_BC_TRACE); + return WasOptionSet(OPTION_TRACE_BC); } @@ -812,14 +812,14 @@ public: wasSet_ |= 1ULL << static_cast(opt); } - void SetEnableDeoptTrace(bool value) + void SetTraceDeopt(bool value) { - enableDeoptTrace_ = value; + traceDeopt_= value; } - bool IsEnableDeoptTrace() const + bool GetTraceDeopt() const { - return enableDeoptTrace_; + return traceDeopt_; } private: static bool StartsWith(const std::string &haystack, const std::string &needle) @@ -870,7 +870,7 @@ private: bool printAnyTypes_ {false}; bool isWorker_ {false}; std::string builtinsDTS_ {""}; - bool enablebcTrace_ {false}; + bool traceBc_ {false}; std::string logLevel_ {"error"}; arg_list_t logDebug_ {{"all"}}; arg_list_t logInfo_ {{"all"}}; @@ -888,7 +888,7 @@ private: bool enablePGOProfiler_ {false}; uint32_t pgoHotnessThreshold_ {2}; std::string pgoProfilerPath_ {""}; - bool enableDeoptTrace_ {false}; + bool traceDeopt_{false}; }; } // namespace panda::ecmascript diff --git a/ecmascript/stubs/runtime_stubs.cpp b/ecmascript/stubs/runtime_stubs.cpp index 58fdbce123..6c7089fa8d 100644 --- a/ecmascript/stubs/runtime_stubs.cpp +++ b/ecmascript/stubs/runtime_stubs.cpp @@ -22,7 +22,7 @@ #include "ecmascript/compiler/call_signature.h" #include "ecmascript/compiler/ecma_opcode_des.h" #include "ecmascript/compiler/rt_call_signature.h" -#include "ecmascript/deoptimizer.h" +#include "ecmascript/deoptimizer/deoptimizer.h" #include "ecmascript/dfx/pgo_profiler/pgo_profiler_manager.h" #include "ecmascript/ecma_macros.h" #include "ecmascript/ecma_vm.h" From cd5f8f2867f59a54274e5f460995141272fed249 Mon Sep 17 00:00:00 2001 From: xujie Date: Thu, 24 Nov 2022 11:35:05 +0800 Subject: [PATCH 08/14] Reserve JSFucntion Slot on OptimizedJSFunctionFrame Issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I62YZR Signed-off-by: xujie Change-Id: I3365d899d821c96ff11f5a9713452a8424cd04bf --- ecmascript/compiler/llvm_ir_builder.cpp | 71 +++++++++++++------ ecmascript/compiler/llvm_ir_builder.h | 8 ++- ecmascript/compiler/tests/stub_tests.cpp | 12 ++-- .../trampoline/aarch64/optimized_call.cpp | 4 +- .../trampoline/x64/optimized_call.cpp | 4 +- ecmascript/frames.cpp | 10 +-- ecmascript/frames.h | 67 +++++++++++++---- 7 files changed, 124 insertions(+), 52 deletions(-) diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index 9a0bd78fc9..fd844b8b76 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -314,7 +314,7 @@ BasicBlockImpl *LLVMIRBuilder::EnsureBBImpl(BasicBlock *bb) const return bb->GetImpl(); } -void LLVMIRBuilder::GenPrologue([[maybe_unused]] LLVMModuleRef &module, LLVMBuilderRef &builder) +void LLVMIRBuilder::GenPrologue() { if (compCfg_->Is32Bit()) { return; @@ -325,25 +325,41 @@ void LLVMIRBuilder::GenPrologue([[maybe_unused]] LLVMModuleRef &module, LLVMBuil } LLVMAddTargetDependentFunctionAttr(function_, "frame-pointer", "all"); - LLVMValueRef llvmFpAddr = CallingFp(module_, builder_, false); - - LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder, llvmFpAddr, slotType_, "cast_int_t"); - LLVMValueRef frameTypeSlotAddr = LLVMBuildSub(builder, frameAddr, LLVMConstInt(slotType_, slotSize_, false), ""); - 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) { + int reservedSlotsSize = 0; + if (frameType == FrameType::OPTIMIZED_FRAME) { + reservedSlotsSize = OptimizedFrame::ComputeReservedSize(slotSize_); 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); + SaveFrameTypeOnFrame(frameType); + } else if (frameType == FrameType::OPTIMIZED_JS_FUNCTION_FRAME) { + reservedSlotsSize = OptimizedJSFunctionFrame::ComputeReservedJSFuncOffset(slotSize_); LLVMAddTargetDependentFunctionAttr(function_, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str()); + auto ArgList = Circuit::GetCircuitRoot(OpCode(OpCode::ARG_LIST)); + auto uses = acc_.Uses(ArgList); + for (auto useIt = uses.begin(); useIt != uses.end(); ++useIt) { + int argth = static_cast(acc_.GetBitField(*useIt)); + LLVMValueRef value = LLVMGetParam(function_, argth); + if (argth == static_cast(CommonArgIdx::LEXENV)) { + SaveLexicalEnvOnOptJSFuncFrame(value); + } else if (argth == static_cast(CommonArgIdx::FUNC)) { + SaveJSFuncOnOptJSFuncFrame(value); + SaveFrameTypeOnFrame(frameType); + } + } } else { LOG_COMPILER(FATAL) << "frameType interpret type error !"; ASSERT_PRINT(static_cast(frameType), "is not support !"); } +} +void LLVMIRBuilder::SaveFrameTypeOnFrame(FrameType frameType) +{ + LLVMValueRef llvmFpAddr = CallingFp(module_, builder_, false); + + LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder_, llvmFpAddr, slotType_, "cast_int_t"); + LLVMValueRef frameTypeSlotAddr = LLVMBuildSub(builder_, frameAddr, LLVMConstInt(slotType_, slotSize_, false), ""); + LLVMValueRef addr = LLVMBuildIntToPtr(builder_, frameTypeSlotAddr, LLVMPointerType(slotType_, 0), "frameType.Addr"); LLVMValueRef llvmFrameType = LLVMConstInt(slotType_, static_cast(frameType), 0); LLVMBuildStore(builder_, llvmFrameType, addr); } @@ -917,7 +933,7 @@ void LLVMIRBuilder::LinkToLLVMCfg(int bbId, const OperandsVector &predecessors) LLVMMoveBasicBlockBefore(preLBB, lBB); } if (isPrologue(bbId)) { - GenPrologue(module_, builder_); + GenPrologue(); } } @@ -1049,28 +1065,36 @@ void LLVMIRBuilder::VisitParameter(GateRef gate) gate2LValue_[gate] = value; // NOTE: caller put args, otherwise crash ASSERT(value != nullptr); - - // add env slot for optimized jsfunction frame - auto frameType = circuit_->GetFrameType(); - if (frameType == panda::ecmascript::FrameType::OPTIMIZED_JS_FUNCTION_FRAME) { - if (argth == static_cast(CommonArgIdx::LEXENV)) { - SaveLexicalEnvOnFrame(value); - } - } } -void LLVMIRBuilder::SaveLexicalEnvOnFrame(LLVMValueRef value) +void LLVMIRBuilder::SaveLexicalEnvOnOptJSFuncFrame(LLVMValueRef value) { + ASSERT(circuit_->GetFrameType() == FrameType::OPTIMIZED_JS_FUNCTION_FRAME); LLVMValueRef llvmFpAddr = CallingFp(module_, builder_, false); LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder_, llvmFpAddr, slotType_, "cast_int_t"); + size_t reservedOffset = OptimizedJSFunctionFrame::ComputeReservedEnvOffset(slotSize_); LLVMValueRef frameEnvSlotAddr = LLVMBuildSub(builder_, frameAddr, LLVMConstInt(slotType_, - static_cast(ReservedSlots::OPTIMIZED_JS_FUNCTION_RESERVED_SLOT) * slotSize_, false), ""); + reservedOffset, false), ""); LLVMValueRef envAddr = LLVMBuildIntToPtr(builder_, frameEnvSlotAddr, LLVMPointerType(slotType_, 0), "env.Addr"); LLVMValueRef envValue = LLVMBuildPtrToInt(builder_, value, slotType_, "cast_to_i64"); LLVMBuildStore(builder_, envValue, envAddr); } +void LLVMIRBuilder::SaveJSFuncOnOptJSFuncFrame(LLVMValueRef value) +{ + ASSERT(circuit_->GetFrameType() == FrameType::OPTIMIZED_JS_FUNCTION_FRAME); + LLVMValueRef llvmFpAddr = CallingFp(module_, builder_, false); + LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder_, llvmFpAddr, slotType_, "cast_int_t"); + size_t reservedOffset = OptimizedJSFunctionFrame::ComputeReservedJSFuncOffset(slotSize_); + LLVMValueRef frameJSFuncSlotAddr = LLVMBuildSub(builder_, frameAddr, LLVMConstInt(slotType_, + reservedOffset, false), ""); + LLVMValueRef jsFuncAddr = LLVMBuildIntToPtr(builder_, frameJSFuncSlotAddr, + LLVMPointerType(slotType_, 0), "jsfunc.Addr"); + LLVMValueRef jsFuncValue = LLVMBuildPtrToInt(builder_, value, slotType_, "cast_to_i64"); + LLVMBuildStore(builder_, jsFuncValue, jsFuncAddr); +} + void LLVMIRBuilder::HandleBranch(GateRef gate) { std::vector ins; @@ -1369,8 +1393,9 @@ void LLVMIRBuilder::VisitGetEnv(GateRef gate) returnType = ConvertLLVMTypeFromGate(gate); LLVMValueRef llvmFpAddr = CallingFp(module_, builder_, false); LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder_, llvmFpAddr, slotType_, "cast_int_t"); + size_t reservedOffset = OptimizedJSFunctionFrame::ComputeReservedEnvOffset(slotSize_); LLVMValueRef frameEnvSlotAddr = LLVMBuildSub(builder_, frameAddr, LLVMConstInt(slotType_, - static_cast(ReservedSlots::OPTIMIZED_JS_FUNCTION_RESERVED_SLOT) * slotSize_, false), ""); + reservedOffset, false), ""); LLVMValueRef envAddr = LLVMBuildIntToPtr(builder_, frameEnvSlotAddr, LLVMPointerType(slotType_, 0), "env.Addr"); envAddr = LLVMBuildPointerCast(builder_, envAddr, LLVMPointerType(returnType, LLVMGetPointerAddressSpace(LLVMTypeOf(envAddr))), ""); diff --git a/ecmascript/compiler/llvm_ir_builder.h b/ecmascript/compiler/llvm_ir_builder.h index 6c303f4cf1..9164a72a21 100644 --- a/ecmascript/compiler/llvm_ir_builder.h +++ b/ecmascript/compiler/llvm_ir_builder.h @@ -263,7 +263,7 @@ private: LLVMValueRef GetCurrentSP(); LLVMValueRef ReadRegister(LLVMModuleRef &module, LLVMBuilderRef &builder, LLVMMetadataRef meta); - void GenPrologue(LLVMModuleRef &module, LLVMBuilderRef &builder); + void GenPrologue(); LLVMBasicBlockRef EnsureLBB(BasicBlock *bb) const; BasicBlockImpl *EnsureBBImpl(BasicBlock *bb) const; void SetToCfg(BasicBlock *bb) const; @@ -330,13 +330,15 @@ private: CallExceptionKind GetCallExceptionKind(size_t index, OpCode op) const; void ComputeArgCountAndBCOffset(size_t &actualNumArgs, LLVMValueRef &bcOffset, const std::vector &inList, CallExceptionKind kind); - void SaveLexicalEnvOnFrame(LLVMValueRef value); + void SaveLexicalEnvOnOptJSFuncFrame(LLVMValueRef value); + void SaveJSFuncOnOptJSFuncFrame(LLVMValueRef value); + void SaveFrameTypeOnFrame(FrameType frameType); LLVMTypeRef GetExperimentalDeoptTy(); LLVMValueRef GetExperimentalDeopt(LLVMModuleRef &module); const CompilationConfig *compCfg_ {nullptr}; const std::vector> *scheduledGates_ {nullptr}; const Circuit *circuit_ {nullptr}; - const GateAccessor acc_; + GateAccessor acc_; BasicBlock *currentBb_ {nullptr}; int lineNumber_ {0}; diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index c4f93e5140..ac34d299d8 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -603,7 +603,7 @@ HWTEST_F_L0(StubTest, JSEntryTest) /* implement stub1 */ LLVMValueRef stub1 = LLVMAddFunction(module, "stub1", LLVMFunctionType(LLVMInt64Type(), paramTys0, 1, 0)); LLVMAddTargetDependentFunctionAttr(stub1, "frame-pointer", "all"); - int reservedSlotsSize = sizeof(uint64_t) * static_cast(ReservedSlots::OPTIMIZED_ENTRY_RESERVED_SLOT); + int reservedSlotsSize = OptimizedEntryFrame::ComputeReservedSize(sizeof(uint64_t)); LLVMAddTargetDependentFunctionAttr(stub1, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str()); LLVMBasicBlockRef entryBb = LLVMAppendBasicBlock(stub1, "entry"); @@ -642,7 +642,7 @@ HWTEST_F_L0(StubTest, JSEntryTest) /* implement stub2 call stub3 */ LLVMValueRef stub2 = LLVMAddFunction(module, "stub2", LLVMFunctionType(LLVMInt64Type(), paramTys0, 1, 0)); LLVMAddTargetDependentFunctionAttr(stub2, "frame-pointer", "all"); - int reservedSlotsSize = sizeof(uint64_t) * static_cast(ReservedSlots::OPTIMIZED_ENTRY_RESERVED_SLOT); + int reservedSlotsSize = OptimizedEntryFrame::ComputeReservedSize(sizeof(uint64_t)); LLVMAddTargetDependentFunctionAttr(stub2, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str()); entryBb = LLVMAppendBasicBlock(stub2, "entry"); @@ -673,7 +673,7 @@ HWTEST_F_L0(StubTest, JSEntryTest) /* implement stub3 call RuntimeFunc2 */ LLVMAddTargetDependentFunctionAttr(stub3, "frame-pointer", "all"); - int reservedSlotsSize = sizeof(uint64_t) * static_cast(ReservedSlots::OPTIMIZED_RESERVED_SLOT); + int reservedSlotsSize = OptimizedFrame::ComputeReservedSize(sizeof(uint64_t)); LLVMAddTargetDependentFunctionAttr(stub3, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str()); entryBb = LLVMAppendBasicBlock(stub3, "entry"); @@ -737,7 +737,7 @@ HWTEST_F_L0(StubTest, Prologue) /* implement main implement */ LLVMValueRef func = LLVMAddFunction(module, "main", LLVMFunctionType(LLVMInt64Type(), nullptr, 0, 0)); LLVMAddTargetDependentFunctionAttr(func, "frame-pointer", "all"); - int reservedSlotsSize = sizeof(uint64_t) * static_cast(ReservedSlots::OPTIMIZED_ENTRY_RESERVED_SLOT); + int reservedSlotsSize = OptimizedEntryFrame::ComputeReservedSize(sizeof(uint64_t)); LLVMAddTargetDependentFunctionAttr(func, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str()); LLVMBasicBlockRef entryBb = LLVMAppendBasicBlock(func, "entry"); @@ -747,7 +747,7 @@ HWTEST_F_L0(StubTest, Prologue) LLVMBuilderRef builderBar = LLVMCreateBuilder(); LLVMValueRef bar = LLVMAddFunction(module, "bar", LLVMFunctionType(LLVMInt64Type(), paramTys0, 2, 0)); LLVMAddTargetDependentFunctionAttr(bar, "frame-pointer", "all"); - int reservedSlotsSize = sizeof(uint64_t) * static_cast(ReservedSlots::OPTIMIZED_RESERVED_SLOT); + int reservedSlotsSize = OptimizedFrame::ComputeReservedSize(sizeof(uint64_t)); LLVMAddTargetDependentFunctionAttr(bar, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str()); LLVMBasicBlockRef entryBbBar = LLVMAppendBasicBlock(bar, "entry"); LLVMPositionBuilderAtEnd(builderBar, entryBbBar); @@ -797,7 +797,7 @@ HWTEST_F_L0(StubTest, CEntryFp) /* implement main call RuntimeFunc */ LLVMValueRef func = LLVMAddFunction(module, "main", LLVMFunctionType(LLVMInt64Type(), paramTys0, 1, 0)); LLVMAddTargetDependentFunctionAttr(func, "frame-pointer", "all"); - int reservedSlotsSize = sizeof(uint64_t) * static_cast(ReservedSlots::OPTIMIZED_ENTRY_RESERVED_SLOT); + int reservedSlotsSize = OptimizedEntryFrame::ComputeReservedSize(sizeof(uint64_t)); 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/optimized_call.cpp b/ecmascript/compiler/trampoline/aarch64/optimized_call.cpp index 2b905f09a3..65ff2b70f3 100644 --- a/ecmascript/compiler/trampoline/aarch64/optimized_call.cpp +++ b/ecmascript/compiler/trampoline/aarch64/optimized_call.cpp @@ -346,7 +346,9 @@ void OptimizedCall::CallBuiltinTrampoline(ExtendedAssembler *assembler) // |--------------------------| OptimizedJSFunctionFrame // | frameType | | // |--------------------------| | -// | lexEnv | v +// | lexEnv | | +// |--------------------------| | +// | call-target | v // +--------------------------+ --------------- void OptimizedCall::GenJSCall(ExtendedAssembler *assembler, bool isNew) diff --git a/ecmascript/compiler/trampoline/x64/optimized_call.cpp b/ecmascript/compiler/trampoline/x64/optimized_call.cpp index 354291de45..46d5d22346 100644 --- a/ecmascript/compiler/trampoline/x64/optimized_call.cpp +++ b/ecmascript/compiler/trampoline/x64/optimized_call.cpp @@ -530,7 +530,9 @@ void OptimizedCall::JSProxyCallInternalWithArgV(ExtendedAssembler *assembler) // |--------------------------| OptimizedJSFunctionFrame // | frameType | | // |--------------------------| | -// | lexEnv | v +// | lexEnv | | +// |--------------------------| | +// | call-target | v // +--------------------------+ --------------- void OptimizedCall::JSCallNew(ExtendedAssembler *assembler) { diff --git a/ecmascript/frames.cpp b/ecmascript/frames.cpp index fb5d075d44..0fbf44aa7a 100644 --- a/ecmascript/frames.cpp +++ b/ecmascript/frames.cpp @@ -387,8 +387,10 @@ ARK_INLINE void OptimizedJSFunctionFrame::GCIterate(const FrameIterator &it, const RootBaseAndDerivedVisitor &derivedVisitor) const { OptimizedJSFunctionFrame *frame = OptimizedJSFunctionFrame::GetFrameFromSp(it.GetSp()); - uintptr_t *envPtr = reinterpret_cast(frame); - uintptr_t envslot = ToUintPtr(envPtr); + uintptr_t *jsFuncPtr = reinterpret_cast(frame); + uintptr_t jsFuncSlot = ToUintPtr(jsFuncPtr); + uintptr_t envslot = jsFuncSlot + sizeof(uintptr_t); + visitor(Root::ROOT_FRAME, ObjectSlot(jsFuncSlot)); visitor(Root::ROOT_FRAME, ObjectSlot(envslot)); uintptr_t *preFrameSp = frame->ComputePrevFrameSp(it); @@ -610,8 +612,8 @@ bool GetTypeOffsetAndPrevOffsetFromFrameType(uintptr_t frameType, uintptr_t &typ prevOffset = OptimizedFrame::GetPrevOffset(); break; case (uintptr_t)(FrameType::OPTIMIZED_ENTRY_FRAME): - typeOffset = MEMBER_OFFSET(OptimizedEntryFrame, type); - prevOffset = MEMBER_OFFSET(OptimizedEntryFrame, preLeaveFrameFp); + typeOffset = OptimizedEntryFrame::GetTypeOffset(); + prevOffset = OptimizedEntryFrame::GetLeaveFrameFpOffset(); break; case (uintptr_t)(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME): typeOffset = OptimizedJSFunctionUnfoldArgVFrame::GetTypeOffset(); diff --git a/ecmascript/frames.h b/ecmascript/frames.h index f0cc675672..60e176fa72 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -138,12 +138,6 @@ enum class FrameType: uintptr_t { BUILTIN_LAST = BUILTIN_ENTRY_FRAME, }; -enum class ReservedSlots: int { - OPTIMIZED_RESERVED_SLOT = 1, - OPTIMIZED_JS_FUNCTION_RESERVED_SLOT = 2, - OPTIMIZED_ENTRY_RESERVED_SLOT = 2, -}; - enum class JSCallMode : uintptr_t { CALL_ARG0 = 0, CALL_ARG1, @@ -188,6 +182,11 @@ public: { return MEMBER_OFFSET(OptimizedFrame, prevFp); } + static size_t ComputeReservedSize(size_t slotSize) + { + size_t slotOffset = static_cast(Index::PrevFpIndex) - static_cast(Index::TypeIndex); + return slotSize * slotOffset; + } private: enum class Index : size_t { TypeIndex = 0, @@ -359,11 +358,14 @@ STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionArgConfigFrame), // |--------------------------| OptimizedJSFunctionFrame // | frameType | | // |--------------------------| | -// | lexEnv | v +// | lexEnv | | +// |--------------------------| | +// | call-target | v // +--------------------------+ --------------- // // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) struct OptimizedJSFunctionFrame : public base::AlignedStruct(Index::PrevFpIndex) - static_cast(Index::EnvIndex); + return slotSize * slotOffset; + } + static size_t ComputeReservedJSFuncOffset(size_t slotSize) + { + size_t slotOffset = static_cast(Index::PrevFpIndex) - static_cast(Index::JSFuncIndex); + return slotSize * slotOffset; + } friend class FrameIterator; void GetDeoptBundleInfo(const FrameIterator &it, std::vector& deopts) const; void GetFuncCalleeRegAndOffset( @@ -439,6 +452,7 @@ private: } // dynamic callee saveregisters for x86-64 + alignas(EAS) JSTaggedValue jsFunc {JSTaggedValue::Undefined()}; alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()}; [[maybe_unused]] alignas(EAS) FrameType type {0}; alignas(EAS) JSTaggedType *prevFp {nullptr}; @@ -460,31 +474,56 @@ STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionFrame), // | preLeaveFrameFp | v // +--------------------------+ ----------------- -struct OptimizedEntryFrame { +struct OptimizedEntryFrame : public base::AlignedStruct { public: enum class CallType : size_t { CALL_FUNC = 0, CALL_NEW, }; - OptimizedEntryFrame() = default; - ~OptimizedEntryFrame() = default; - JSTaggedType *preLeaveFrameFp; - [[maybe_unused]] FrameType type; - JSTaggedType *prevFp; + + enum class Index : size_t { + PreLeaveFrameFpIndex = 0, + TypeIndex, + PrevFpIndex, + NumOfMembers + }; + + static size_t GetTypeOffset() + { + return MEMBER_OFFSET(OptimizedEntryFrame, type); + } + + static size_t GetLeaveFrameFpOffset() + { + return MEMBER_OFFSET(OptimizedEntryFrame, preLeaveFrameFp); + } inline JSTaggedType* GetPrevFrameFp() { return preLeaveFrameFp; } + + static size_t ComputeReservedSize(size_t slotSize) + { + size_t slotOffset = static_cast(Index::PrevFpIndex) - static_cast(Index::PreLeaveFrameFpIndex); + return slotSize * slotOffset; + } friend class FrameIterator; private: + alignas(EAS) JSTaggedType *preLeaveFrameFp {nullptr}; + alignas(EAS) [[maybe_unused]] FrameType type {0}; + alignas(EAS) [[maybe_unused]] JSTaggedType *prevFp {nullptr}; static OptimizedEntryFrame* GetFrameFromSp(const JSTaggedType *sp) { return reinterpret_cast(reinterpret_cast(sp) - MEMBER_OFFSET(OptimizedEntryFrame, prevFp)); } }; +STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedEntryFrame), OptimizedEntryFrame::SizeArch32, OptimizedEntryFrame::SizeArch64); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) struct InterpretedFrameBase : public base::AlignedStruct Date: Sat, 26 Nov 2022 10:37:17 +0800 Subject: [PATCH 09/14] The use of security functions 'memcpy_s' here will have a greater impact on performance Signed-off-by: linxiang Change-Id: I8741ea1b5286ba7cb0f7c9f8b0e743d7b6ed59bb --- ecmascript/base/bit_helper.h | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/ecmascript/base/bit_helper.h b/ecmascript/base/bit_helper.h index d33fcc1404..07ebd7ef58 100644 --- a/ecmascript/base/bit_helper.h +++ b/ecmascript/base/bit_helper.h @@ -19,13 +19,8 @@ #include #include #include -#include -#include #include -#include "ecmascript/log_wrapper.h" -#include "ecmascript/log.h" - namespace panda::ecmascript::base { template inline constexpr uint32_t CountLeadingZeros(T value) @@ -129,11 +124,9 @@ inline To bit_cast(const From &src) noexcept // NOLINT(readability-identifier-n { static_assert(sizeof(To) == sizeof(From), "size of the types must be equal"); To dst; - errno_t res = memcpy_s(&dst, sizeof(To), &src, sizeof(To)); - if (res != EOK) { - LOG_FULL(FATAL) << "memcpy_s failed"; - UNREACHABLE(); - } + // The use of security functions 'memccpy_s' here will have a greater impact on performance + // todo use union instance of memcpy + memcpy(&dst, &src, sizeof(To)); return dst; } From e326b06a805854bcb681f1d89574ca94b5332f50 Mon Sep 17 00:00:00 2001 From: Zhenyu Pan Date: Tue, 22 Nov 2022 17:17:11 +0800 Subject: [PATCH 10/14] Cache ICU objects to reduce memory cost and improve performance for specific situation Issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I62IQO Signed-off-by: Zhenyu Pan Change-Id: I1a71fe8a314f41278c0a5655c8ea9384097068c8 --- ecmascript/builtins/builtins_date.cpp | 54 +++++++++++++++++++++ ecmascript/ecma_vm.h | 41 ++++++++++++++++ ecmascript/js_date.cpp | 67 --------------------------- ecmascript/js_date.h | 9 ---- ecmascript/js_date_time_format.cpp | 21 +++++++++ ecmascript/js_date_time_format.h | 5 ++ 6 files changed, 121 insertions(+), 76 deletions(-) diff --git a/ecmascript/builtins/builtins_date.cpp b/ecmascript/builtins/builtins_date.cpp index e911127594..445d2b58c8 100644 --- a/ecmascript/builtins/builtins_date.cpp +++ b/ecmascript/builtins/builtins_date.cpp @@ -259,6 +259,16 @@ JSTaggedValue BuiltinsDate::ToLocaleString(EcmaRuntimeCallInfo *argv) // Let options be ? ToDateTimeOptions(options, "any", "all"). JSHandle locales = GetCallArg(argv, 0); JSHandle options = GetCallArg(argv, 1); + bool cacheable = (locales->IsUndefined() || locales->IsString()) && options->IsUndefined(); + if (cacheable) { + auto simpleDateFormat = JSDateTimeFormat::GetCachedIcuSimpleDateFormat(thread, locales, + IcuFormatterType::SimpleDateFormatDefault); + if (simpleDateFormat != nullptr) { + JSHandle result = JSDateTimeFormat::FormatDateTime(thread, simpleDateFormat, x); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + return result.GetTaggedValue(); + } + } JSHandle dateTimeOptions = JSDateTimeFormat::ToDateTimeOptions(thread, options, RequiredOption::ANY, DefaultsOption::ALL); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); @@ -269,9 +279,17 @@ JSTaggedValue BuiltinsDate::ToLocaleString(EcmaRuntimeCallInfo *argv) JSHandle dtf = JSDateTimeFormat::InitializeDateTimeFormat( thread, JSHandle::Cast(obj), locales, JSHandle::Cast(dateTimeOptions)); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + if (cacheable) { + auto icuSimpleDateFormat = dtf->GetIcuSimpleDateFormat(); + std::string cacheEntry = + locales->IsUndefined() ? "" : EcmaStringAccessor(locales.GetTaggedValue()).ToStdString(); + ecmaVm->SetIcuFormatterToCache(IcuFormatterType::SimpleDateFormatDefault, cacheEntry, + std::make_shared(*icuSimpleDateFormat)); + } // Return ? FormatDateTime(dateFormat, x). JSHandle result = JSDateTimeFormat::FormatDateTime(thread, dtf, x); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return result.GetTaggedValue(); } @@ -302,6 +320,16 @@ JSTaggedValue BuiltinsDate::ToLocaleDateString(EcmaRuntimeCallInfo *argv) // Let options be ? ToDateTimeOptions(options, "any", "all"). JSHandle locales = GetCallArg(argv, 0); JSHandle options = GetCallArg(argv, 1); + bool cacheable = (locales->IsUndefined() || locales->IsString()) && options->IsUndefined(); + if (cacheable) { + auto simpleDateFormat = JSDateTimeFormat::GetCachedIcuSimpleDateFormat(thread, locales, + IcuFormatterType::SimpleDateFormatDate); + if (simpleDateFormat != nullptr) { + JSHandle result = JSDateTimeFormat::FormatDateTime(thread, simpleDateFormat, x); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + return result.GetTaggedValue(); + } + } JSHandle dateTimeOptions = JSDateTimeFormat::ToDateTimeOptions(thread, options, RequiredOption::DATE, DefaultsOption::DATE); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); @@ -312,9 +340,17 @@ JSTaggedValue BuiltinsDate::ToLocaleDateString(EcmaRuntimeCallInfo *argv) JSHandle dtf = JSDateTimeFormat::InitializeDateTimeFormat( thread, JSHandle::Cast(obj), locales, JSHandle::Cast(dateTimeOptions)); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + if (cacheable) { + auto icuSimpleDateFormat = dtf->GetIcuSimpleDateFormat(); + std::string cacheEntry = + locales->IsUndefined() ? "" : EcmaStringAccessor(locales.GetTaggedValue()).ToStdString(); + ecmaVm->SetIcuFormatterToCache(IcuFormatterType::SimpleDateFormatDate, cacheEntry, + std::make_shared(*icuSimpleDateFormat)); + } // Return ? FormatDateTime(dateFormat, x). JSHandle result = JSDateTimeFormat::FormatDateTime(thread, dtf, x); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return result.GetTaggedValue(); } @@ -345,6 +381,16 @@ JSTaggedValue BuiltinsDate::ToLocaleTimeString(EcmaRuntimeCallInfo *argv) // Let options be ? ToDateTimeOptions(options, "any", "all"). JSHandle locales = GetCallArg(argv, 0); JSHandle options = GetCallArg(argv, 1); + bool cacheable = (locales->IsUndefined() || locales->IsString()) && options->IsUndefined(); + if (cacheable) { + auto simpleDateFormat = JSDateTimeFormat::GetCachedIcuSimpleDateFormat(thread, locales, + IcuFormatterType::SimpleDateFormatTime); + if (simpleDateFormat != nullptr) { + JSHandle result = JSDateTimeFormat::FormatDateTime(thread, simpleDateFormat, x); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + return result.GetTaggedValue(); + } + } JSHandle dateTimeOptions = JSDateTimeFormat::ToDateTimeOptions(thread, options, RequiredOption::TIME, DefaultsOption::TIME); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); @@ -355,9 +401,17 @@ JSTaggedValue BuiltinsDate::ToLocaleTimeString(EcmaRuntimeCallInfo *argv) JSHandle dtf = JSDateTimeFormat::InitializeDateTimeFormat( thread, JSHandle::Cast(obj), locales, JSHandle::Cast(dateTimeOptions)); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + if (cacheable) { + auto icuSimpleDateFormat = dtf->GetIcuSimpleDateFormat(); + std::string cacheEntry = + locales->IsUndefined() ? "" : EcmaStringAccessor(locales.GetTaggedValue()).ToStdString(); + ecmaVm->SetIcuFormatterToCache(IcuFormatterType::SimpleDateFormatTime, cacheEntry, + std::make_shared(*icuSimpleDateFormat)); + } // Return ? FormatDateTime(dateFormat, x). JSHandle result = JSDateTimeFormat::FormatDateTime(thread, dtf, x); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return result.GetTaggedValue(); } } // namespace panda::ecmascript::builtins diff --git a/ecmascript/ecma_vm.h b/ecmascript/ecma_vm.h index 8127f7287b..d40ce95601 100644 --- a/ecmascript/ecma_vm.h +++ b/ecmascript/ecma_vm.h @@ -108,6 +108,11 @@ enum class MethodIndex : uint8_t { METHOD_END }; +enum class IcuFormatterType { + SimpleDateFormatDefault, + SimpleDateFormatDate, + SimpleDateFormatTime +}; using HostPromiseRejectionTracker = void (*)(const EcmaVM* vm, const JSHandle promise, const JSHandle reason, @@ -512,6 +517,31 @@ public: JSTaggedValue ExecuteAot(size_t actualNumArgs, JSTaggedType *args, const JSTaggedType *prevFp, OptimizedEntryFrame::CallType callType); + + // For icu objects cache + void SetIcuFormatterToCache(IcuFormatterType type, const std::string &locale, std::shared_ptr icuObj) + { + EcmaVM::IcuFormatter icuFormatter = IcuFormatter(locale, icuObj); + icuObjCache_.insert({type, std::move(icuFormatter)}); + } + + icu::UMemory *GetIcuFormatterFromCache(IcuFormatterType type, std::string locale) + { + auto iter = icuObjCache_.find(type); + EcmaVM::IcuFormatter icuFormatter; + if (iter != icuObjCache_.end()) { + icuFormatter = iter->second; + if (icuFormatter.locale == locale) { + return icuFormatter.icuObj.get(); + } + } + return nullptr; + } + + void ClearIcuCache() + { + icuObjCache_.clear(); + } protected: void HandleUncaughtException(TaggedObject *exception); @@ -632,6 +662,17 @@ private: // PGO Profiler PGOProfiler *pgoProfiler_; + // For icu objects cache + struct IcuFormatter { + std::string locale; + std::shared_ptr icuObj; + + IcuFormatter() = default; + IcuFormatter(const std::string &locale, std::shared_ptr icuObj) + : locale(locale), icuObj(std::move(icuObj)) {} + }; + std::unordered_map icuObjCache_; + friend class Snapshot; friend class SnapshotProcessor; friend class ObjectFactory; diff --git a/ecmascript/js_date.cpp b/ecmascript/js_date.cpp index 46c2f4652f..4a399f8be1 100644 --- a/ecmascript/js_date.cpp +++ b/ecmascript/js_date.cpp @@ -756,73 +756,6 @@ JSTaggedValue JSDate::ToISOString(JSThread *thread) const return thread->GetEcmaVM()->GetFactory()->NewFromASCII(str).GetTaggedValue(); } -CString JSDate::GetLocaleTimeStr(const std::array &fields) const -{ - CString hour; - if (fields[HOUR] > MOUTH_PER_YEAR) { - hour = ToCString(fields[HOUR] - MOUTH_PER_YEAR); - } else { - hour = ToCString(fields[HOUR]); - } - CString minute = ToCString(fields[MIN]); - CString second = StrToTargetLength(ToCString(fields[SEC]), STR_LENGTH_OTHERS); - CString str = hour + COLON + minute + COLON + second; - if (fields[HOUR] >= MOUTH_PER_YEAR) { - str = "下午" + str; - } else { - str = "上午" + str; - } - return str; -} - -CString JSDate::GetLocaleDateStr(const std::array &fields) const -{ - CString year; - if (fields[YEAR] < 0) { - year = ToCString(-fields[YEAR] + 1); - } else { - year = ToCString(fields[YEAR]); - } - CString month = ToCString(fields[MONTH] + 1); - CString day = ToCString(fields[DAYS]); - CString str = year + VIRGULE + month + VIRGULE + day; - return str; -} - -// 20.4.4.38 -JSTaggedValue JSDate::ToLocaleDateString(JSThread *thread) const -{ - std::array fields = {0}; - if (!GetThisDateValues(&fields, true)) { - return JSTaggedValue(base::NAN_VALUE); - } - CString str = GetLocaleDateStr(fields); - return thread->GetEcmaVM()->GetFactory()->NewFromASCII(str).GetTaggedValue(); -} - -// 20.4.4.39 -JSTaggedValue JSDate::ToLocaleString(JSThread *thread) const -{ - std::array fields = {0}; - if (!GetThisDateValues(&fields, true)) { - return JSTaggedValue(base::NAN_VALUE); - } - CString strDate = GetLocaleDateStr(fields); - CString strTime = GetLocaleTimeStr(fields); - return thread->GetEcmaVM()->GetFactory()->NewFromASCII(strDate + SPACE + strTime).GetTaggedValue(); -} - -// 20.4.4.40 -JSTaggedValue JSDate::ToLocaleTimeString(JSThread *thread) const -{ - std::array fields = {0}; - if (!GetThisDateValues(&fields, true)) { - return JSTaggedValue(base::NAN_VALUE); - } - CString str = GetLocaleTimeStr(fields); - return thread->GetEcmaVM()->GetFactory()->NewFromASCII(str).GetTaggedValue(); -} - // 20.4.4.41 JSTaggedValue JSDate::ToString(JSThread *thread) const { diff --git a/ecmascript/js_date.h b/ecmascript/js_date.h index 374c3ec319..9a562a0e7b 100644 --- a/ecmascript/js_date.h +++ b/ecmascript/js_date.h @@ -129,15 +129,6 @@ public: // 20.4.4.36 JSTaggedValue ToISOString(JSThread *thread) const; - // 20.4.4.38 - JSTaggedValue ToLocaleDateString(JSThread *thread) const; - - // 20.4.4.39 - JSTaggedValue ToLocaleString(JSThread *thread) const; - - // 20.4.4.40 - JSTaggedValue ToLocaleTimeString(JSThread *thread) const; - // 20.4.4.41 JSTaggedValue ToString(JSThread *thread) const; diff --git a/ecmascript/js_date_time_format.cpp b/ecmascript/js_date_time_format.cpp index 7933bf8080..26506f0a45 100644 --- a/ecmascript/js_date_time_format.cpp +++ b/ecmascript/js_date_time_format.cpp @@ -472,6 +472,19 @@ JSHandle JSDateTimeFormat::InitializeDateTimeFormat(JSThread * return dateTimeFormat; } +icu::SimpleDateFormat *JSDateTimeFormat::GetCachedIcuSimpleDateFormat(JSThread *thread, + const JSHandle &locales, + IcuFormatterType type) +{ + std::string cacheEntry = locales->IsUndefined() ? "" : EcmaStringAccessor(locales.GetTaggedValue()).ToStdString(); + EcmaVM *ecmaVm = thread->GetEcmaVM(); + icu::UMemory *cachedSimpleDateFormat = ecmaVm->GetIcuFormatterFromCache(type, cacheEntry); + if (cachedSimpleDateFormat != nullptr) { + return static_cast(cachedSimpleDateFormat); + } + return nullptr; +} + // 13.1.2 ToDateTimeOptions (options, required, defaults) JSHandle JSDateTimeFormat::ToDateTimeOptions(JSThread *thread, const JSHandle &options, const RequiredOption &required, const DefaultsOption &defaults) @@ -606,6 +619,14 @@ JSHandle JSDateTimeFormat::FormatDateTime(JSThread *thread, const JSHandle &dateTimeFormat, double x) { icu::SimpleDateFormat *simpleDateFormat = dateTimeFormat->GetIcuSimpleDateFormat(); + JSHandle res = FormatDateTime(thread, simpleDateFormat, x); + RETURN_HANDLE_IF_ABRUPT_COMPLETION(EcmaString, thread); + return res; +} + +JSHandle JSDateTimeFormat::FormatDateTime(JSThread *thread, + const icu::SimpleDateFormat *simpleDateFormat, double x) +{ // 1. Let parts be ? PartitionDateTimePattern(dateTimeFormat, x). double xValue = JSDate::TimeClip(x); if (std::isnan(xValue)) { diff --git a/ecmascript/js_date_time_format.h b/ecmascript/js_date_time_format.h index 6a04a648e9..66c89fd9bc 100644 --- a/ecmascript/js_date_time_format.h +++ b/ecmascript/js_date_time_format.h @@ -120,6 +120,9 @@ public: static void SetIcuSimpleDateFormat(JSThread *thread, JSHandle obj, const icu::SimpleDateFormat &icuSimpleDateTimeFormat, const DeleteEntryPoint &callback); static void FreeSimpleDateFormat(void *pointer, void *data); + static icu::SimpleDateFormat *GetCachedIcuSimpleDateFormat(JSThread *thread, + const JSHandle &locales, + IcuFormatterType type); // 13.1.1 InitializeDateTimeFormat (dateTimeFormat, locales, options) static JSHandle InitializeDateTimeFormat(JSThread *thread, @@ -134,6 +137,8 @@ public: // 13.1.7 FormatDateTime(dateTimeFormat, x) static JSHandle FormatDateTime(JSThread *thread, const JSHandle &dateTimeFormat, double x); + static JSHandle FormatDateTime(JSThread *thread, const icu::SimpleDateFormat *simpleDateFormat, + double x); // 13.1.8 FormatDateTimeToParts (dateTimeFormat, x) static JSHandle FormatDateTimeToParts(JSThread *thread, const JSHandle &dateTimeFormat, From 40393ed2f1ac634b639c4ec1735766b8d90b381d Mon Sep 17 00:00:00 2001 From: g00416891 Date: Sat, 26 Nov 2022 15:24:12 +0800 Subject: [PATCH 11/14] Fix code check Signed-off-by: g00416891 Change-Id: I6432ff57276e0671b985cb7efa838253e9864c73 --- ecmascript/aot_file_manager.cpp | 7 +------ ecmascript/aot_file_manager.h | 2 +- ecmascript/base/file_path_helper.cpp | 1 - ecmascript/deoptimizer/deoptimizer.cpp | 2 +- ecmascript/dfx/cpu_profiler/cpu_profiler.cpp | 6 +++--- ecmascript/frames.cpp | 4 ++-- ecmascript/js_bigint.h | 2 +- ecmascript/js_locale.h | 2 +- ecmascript/js_thread.cpp | 6 +++--- ecmascript/jspandafile/js_pandafile_manager.cpp | 2 +- ecmascript/jspandafile/literal_data_extractor.cpp | 2 +- ecmascript/module/js_module_manager.cpp | 12 ++++++------ ecmascript/module/js_module_source_text.cpp | 2 +- 13 files changed, 22 insertions(+), 28 deletions(-) diff --git a/ecmascript/aot_file_manager.cpp b/ecmascript/aot_file_manager.cpp index 5e31384bfc..1c3e2ebc1a 100644 --- a/ecmascript/aot_file_manager.cpp +++ b/ecmascript/aot_file_manager.cpp @@ -657,19 +657,14 @@ bool AOTFileManager::GetAbsolutePath(const std::string &relativePath, std::strin char buffer[PATH_MAX] = {0}; #ifndef PANDA_TARGET_WINDOWS auto path = realpath(relativePath.c_str(), buffer); - if (path == nullptr) { - return false; - } - absPath = std::string(path); - return true; #else auto path = _fullpath(buffer, relativePath.c_str(), sizeof(buffer) - 1); +#endif if (path == nullptr) { return false; } absPath = std::string(buffer); return true; -#endif } void BinaryBufferParser::ParseBuffer(void *dst, uint32_t count) diff --git a/ecmascript/aot_file_manager.h b/ecmascript/aot_file_manager.h index 2fe7632268..181f646856 100644 --- a/ecmascript/aot_file_manager.h +++ b/ecmascript/aot_file_manager.h @@ -241,7 +241,7 @@ public: { FuncEntryDes des; if (memset_s(&des, sizeof(des), 0, sizeof(des)) != EOK) { - LOG_FULL(FATAL) << "memset failed"; + LOG_FULL(FATAL) << "memset_s failed"; return; } des.kind_ = kind; diff --git a/ecmascript/base/file_path_helper.cpp b/ecmascript/base/file_path_helper.cpp index 61798265a4..dfe176405d 100644 --- a/ecmascript/base/file_path_helper.cpp +++ b/ecmascript/base/file_path_helper.cpp @@ -27,7 +27,6 @@ namespace panda::ecmascript::base { bool FilePathHelper::RealPath(const std::string &path, std::string &realPath, [[maybe_unused]] bool readOnly) { - realPath = ""; if (path.empty() || path.size() > PATH_MAX) { LOG_ECMA(WARN) << "File path is illeage"; return false; diff --git a/ecmascript/deoptimizer/deoptimizer.cpp b/ecmascript/deoptimizer/deoptimizer.cpp index aed09291ca..73e21bd558 100644 --- a/ecmascript/deoptimizer/deoptimizer.cpp +++ b/ecmascript/deoptimizer/deoptimizer.cpp @@ -136,7 +136,7 @@ void Deoptimizier::CollectDeoptBundleVec(std::vector& deoptBun case FrameType::LEAVE_FRAME: break; default: { - LOG_ECMA(FATAL) << "frame type error!"; + LOG_FULL(FATAL) << "frame type error!"; UNREACHABLE(); } } diff --git a/ecmascript/dfx/cpu_profiler/cpu_profiler.cpp b/ecmascript/dfx/cpu_profiler/cpu_profiler.cpp index 64bcf99b30..3ea4aaadf4 100644 --- a/ecmascript/dfx/cpu_profiler/cpu_profiler.cpp +++ b/ecmascript/dfx/cpu_profiler/cpu_profiler.cpp @@ -470,11 +470,11 @@ void CpuProfiler::GetStackSignalHandler(int signal, [[maybe_unused]] siginfo_t * fp = reinterpret_cast(mcontext.regs[29]); // FP is an alias for x29. sp = reinterpret_cast(mcontext.sp); #else - LOG_ECMA(FATAL) << "Cpuprofiler does not currently support other platforms, please run on x64 and arm64"; + LOG_FULL(FATAL) << "Cpuprofiler does not currently support other platforms, please run on x64 and arm64"; return; #endif if (reinterpret_cast(sp) > reinterpret_cast(fp)) { - LOG_ECMA(FATAL) << "sp > fp, stack frame exception"; + LOG_FULL(FATAL) << "sp > fp, stack frame exception"; } if (profiler->CheckFrameType(thread, reinterpret_cast(fp))) { FrameHandler frameHandler(thread, fp); @@ -524,7 +524,7 @@ bool CpuProfiler::IsAddrAtStub(void *context) #elif defined(PANDA_TARGET_ARM64) pc = static_cast(mcontext.pc); #else - LOG_ECMA(FATAL) << "Cpuprofiler does not currently support other platforms, please run on x64 and arm64"; + LOG_FULL(FATAL) << "Cpuprofiler does not currently support other platforms, please run on x64 and arm64"; return true; #endif AOTFileManager *loader = vm_->GetAOTFileManager(); diff --git a/ecmascript/frames.cpp b/ecmascript/frames.cpp index 0fbf44aa7a..1312ea29c4 100644 --- a/ecmascript/frames.cpp +++ b/ecmascript/frames.cpp @@ -296,7 +296,7 @@ uintptr_t FrameIterator::GetPrevFrameCallSiteSp([[maybe_unused]] uintptr_t curPc return 0; } default: { - LOG_ECMA(FATAL) << "frame type error!"; + LOG_FULL(FATAL) << "frame type error!"; } } } @@ -323,7 +323,7 @@ uintptr_t FrameIterator::GetPrevFrame() const break; } default: { - LOG_ECMA(FATAL) << "frame type error!"; + LOG_FULL(FATAL) << "frame type error!"; } } return end; diff --git a/ecmascript/js_bigint.h b/ecmascript/js_bigint.h index dcfd5c6039..243c146ea4 100644 --- a/ecmascript/js_bigint.h +++ b/ecmascript/js_bigint.h @@ -131,7 +131,7 @@ public: { uint32_t size = GetLength() * sizeof(uint32_t); if (memset_s(GetData(), size, 0, size) != EOK) { - LOG_FULL(FATAL) << "memset failed"; + LOG_FULL(FATAL) << "memset_s failed"; UNREACHABLE(); } } diff --git a/ecmascript/js_locale.h b/ecmascript/js_locale.h index 587fec256a..8e9398419d 100644 --- a/ecmascript/js_locale.h +++ b/ecmascript/js_locale.h @@ -385,7 +385,7 @@ public: sequence = nullptr; return false; } - int32_t size; + int32_t size = 0; const char *element = sequence->next(&size, status); while (U_SUCCESS(status) && element != nullptr) { if (strcmp(outdatedType, element) == 0) { diff --git a/ecmascript/js_thread.cpp b/ecmascript/js_thread.cpp index f0c8bc447d..614c7b37fe 100644 --- a/ecmascript/js_thread.cpp +++ b/ecmascript/js_thread.cpp @@ -304,7 +304,7 @@ void JSThread::ShrinkHandleStorage(int prevIndex) #if ECMASCRIPT_ENABLE_ZAP_MEM uintptr_t size = ToUintPtr(handleScopeStorageEnd_) - ToUintPtr(handleScopeStorageNext_); if (memset_s(handleScopeStorageNext_, size, 0, size) != EOK) { - LOG_FULL(FATAL) << "memcpy_s failed"; + LOG_FULL(FATAL) << "memset_s failed"; UNREACHABLE(); } for (int32_t i = currentHandleStorageIndex_ + 1; i < lastIndex; i++) { @@ -312,7 +312,7 @@ void JSThread::ShrinkHandleStorage(int prevIndex) NODE_BLOCK_SIZE * sizeof(JSTaggedType), 0, NODE_BLOCK_SIZE * sizeof(JSTaggedType)) != EOK) { - LOG_FULL(FATAL) << "memcpy_s failed"; + LOG_FULL(FATAL) << "memset_s failed"; UNREACHABLE(); } } @@ -446,7 +446,7 @@ size_t JSThread::GetAsmStackLimit() // when push other data. result += EcmaParamConfiguration::GetDefaultReservedStackSize(); if (threadStackStart <= result) { - LOG_ECMA(FATAL) << "Too small stackSize to run jsvm"; + LOG_FULL(FATAL) << "Too small stackSize to run jsvm"; } return result; #else diff --git a/ecmascript/jspandafile/js_pandafile_manager.cpp b/ecmascript/jspandafile/js_pandafile_manager.cpp index 07baa4db6c..2c55d5dd3d 100644 --- a/ecmascript/jspandafile/js_pandafile_manager.cpp +++ b/ecmascript/jspandafile/js_pandafile_manager.cpp @@ -264,7 +264,7 @@ void *JSPandaFileManager::JSPandaFileAllocator::AllocateBuffer(size_t size) } #if ECMASCRIPT_ENABLE_ZAP_MEM if (memset_s(ptr, size, INVALID_VALUE, size) != EOK) { - LOG_ECMA_MEM(FATAL) << "memset failed"; + LOG_ECMA_MEM(FATAL) << "memset_s failed"; UNREACHABLE(); } #endif diff --git a/ecmascript/jspandafile/literal_data_extractor.cpp b/ecmascript/jspandafile/literal_data_extractor.cpp index e6583f0e44..026c6a168f 100644 --- a/ecmascript/jspandafile/literal_data_extractor.cpp +++ b/ecmascript/jspandafile/literal_data_extractor.cpp @@ -556,7 +556,7 @@ JSHandle LiteralDataExtractor::GetTypeLiteral(JSThread *thread, con break; } default: { - LOG_ECMA(FATAL) << "type literal should not exist LiteralTag: " << static_cast(tag); + LOG_FULL(FATAL) << "type literal should not exist LiteralTag: " << static_cast(tag); break; } } diff --git a/ecmascript/module/js_module_manager.cpp b/ecmascript/module/js_module_manager.cpp index 540ea1811d..d3867304c1 100644 --- a/ecmascript/module/js_module_manager.cpp +++ b/ecmascript/module/js_module_manager.cpp @@ -265,7 +265,7 @@ JSHandle ModuleManager::HostResolveImportedModuleWithMerge(con const JSPandaFile *jsPandaFile = JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, moduleFileName, recordName.c_str()); if (jsPandaFile == nullptr) { - LOG_ECMA(FATAL) << "open jsPandaFile " << moduleFileName << " error"; + LOG_FULL(FATAL) << "open jsPandaFile " << moduleFileName << " error"; UNREACHABLE(); } @@ -289,7 +289,7 @@ JSHandle ModuleManager::HostResolveImportedModule(const CStrin if (AOTFileManager::GetAbsolutePath(referencingModule, moduleFileName)) { referencingHandle = factory->NewFromUtf8(moduleFileName); } else { - LOG_ECMA(FATAL) << "absolute " << referencingModule << " path error"; + LOG_FULL(FATAL) << "absolute " << referencingModule << " path error"; UNREACHABLE(); } } @@ -303,7 +303,7 @@ JSHandle ModuleManager::HostResolveImportedModule(const CStrin const JSPandaFile *jsPandaFile = JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, moduleFileName, JSPandaFile::ENTRY_MAIN_FUNCTION); if (jsPandaFile == nullptr) { - LOG_ECMA(FATAL) << "open jsPandaFile " << moduleFileName << " error"; + LOG_FULL(FATAL) << "open jsPandaFile " << moduleFileName << " error"; UNREACHABLE(); } @@ -327,7 +327,7 @@ JSHandle ModuleManager::HostResolveImportedModule(const void * JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, filename, JSPandaFile::ENTRY_MAIN_FUNCTION, buffer, size); if (jsPandaFile == nullptr) { - LOG_ECMA(FATAL) << "open jsPandaFile " << filename << " error"; + LOG_FULL(FATAL) << "open jsPandaFile " << filename << " error"; UNREACHABLE(); } @@ -344,7 +344,7 @@ JSHandle ModuleManager::ResolveModule(JSThread *thread, const } else if (jsPandaFile->IsModule()) { moduleRecord = ModuleDataExtractor::ParseModule(thread, jsPandaFile, moduleFileName, moduleFileName); } else { - LOG_ECMA(FATAL) << "jsPandaFile: " << moduleFileName << " is not CjsModule or EcmaModule"; + LOG_FULL(FATAL) << "jsPandaFile: " << moduleFileName << " is not CjsModule or EcmaModule"; UNREACHABLE(); } @@ -367,7 +367,7 @@ JSHandle ModuleManager::ResolveModuleWithMerge( } else if (jsPandaFile->IsModule(recordName)) { moduleRecord = ModuleDataExtractor::ParseModule(thread, jsPandaFile, recordName, moduleFileName); } else { - LOG_ECMA(FATAL) << "jsPandaFile: " << moduleFileName << " is not CjsModule or EcmaModule"; + LOG_FULL(FATAL) << "jsPandaFile: " << moduleFileName << " is not CjsModule or EcmaModule"; UNREACHABLE(); } diff --git a/ecmascript/module/js_module_source_text.cpp b/ecmascript/module/js_module_source_text.cpp index 69a8565d49..670464503e 100644 --- a/ecmascript/module/js_module_source_text.cpp +++ b/ecmascript/module/js_module_source_text.cpp @@ -789,7 +789,7 @@ void SourceTextModule::ModuleExecution(JSThread *thread, const JSHandle Date: Thu, 24 Nov 2022 11:48:02 +0800 Subject: [PATCH 12/14] bug fix for aot file manager 1. Return the constantpool with HOLE value when other worker try to obtain the snapshot constantpool from aot_file_manager 2. Information sharing of '.an' file: make each an file only read once Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I62V6O Signed-off-by: weng-xi Change-Id: I6aa807faa8ae6dd7934edfb3a84d8d0df070e4b7 --- ecmascript/aot_file_manager.cpp | 167 ++++++++++++++++++------ ecmascript/aot_file_manager.h | 40 ++++-- ecmascript/jspandafile/program_object.h | 5 +- 3 files changed, 161 insertions(+), 51 deletions(-) diff --git a/ecmascript/aot_file_manager.cpp b/ecmascript/aot_file_manager.cpp index 66835e6ac0..42deb244a5 100644 --- a/ecmascript/aot_file_manager.cpp +++ b/ecmascript/aot_file_manager.cpp @@ -208,6 +208,113 @@ bool StubFileInfo::Load(EcmaVM *vm) return true; } +AnFileDataManager *AnFileDataManager::GetInstance() +{ + static AnFileDataManager anFileDataManager; + return &anFileDataManager; +} + +AnFileDataManager::~AnFileDataManager() +{ + os::memory::LockHolder lock(lock_); + auto iter = loadedData_.begin(); + while (iter != loadedData_.end()) { + void *poolAddr = iter->second->poolAddr; + size_t poolSize = iter->second->poolSize; + MemMapAllocator::GetInstance()->Free(poolAddr, poolSize, false); + iter = loadedData_.erase(iter); + } +} + +bool AnFileDataManager::SafeLoad(const std::string &filename) +{ + if (!AOTFileInfo::VerifyFilePath(filename)) { + LOG_COMPILER(ERROR) << "Can not load aot file from path [ " << filename << " ], " + << "please execute ark_aot_compiler with options --aot-file."; + UNREACHABLE(); + return false; + } + + os::memory::LockHolder lock(lock_); + const CString &cstrFileName = ConvertToString(filename); + const std::shared_ptr anFileData = UnsafeFind(cstrFileName); + if (anFileData != nullptr) { + return true; + } + if (!UnsafeLoadData(cstrFileName)) { + return false; + } + return true; +} + +std::shared_ptr AnFileDataManager::UnsafeFind(const CString &filename) const +{ + // note: This method is not thread-safe + // need to ensure that the instance of AnFileDataManager has been locked before use + const auto iter = loadedData_.find(filename); + if (iter == loadedData_.end()) { + return nullptr; + } + return iter->second; +} + +std::shared_ptr AnFileDataManager::SafeGetAnFileData(const CString &filename) +{ + os::memory::LockHolder lock(lock_); + return UnsafeFind(filename); +} + +bool AnFileDataManager::UnsafeLoadData(const CString &filename) +{ + std::ifstream file(filename.c_str(), std::ofstream::binary); + if (!file.good()) { + LOG_COMPILER(ERROR) << "Fail to load an file: " << filename.c_str(); + file.close(); + return false; + } + + std::array anVersion; + file.read(reinterpret_cast(anVersion.data()), sizeof(uint8_t) * AOTFileManager::AOT_VERSION_SIZE); + if (anVersion != AOTFileManager::AOT_VERSION) { + auto convToStr = [] (std::array version) -> std::string { + std::string ret = ""; + for (size_t i = 0; i < AOTFileManager::AOT_VERSION_SIZE; ++i) { + if (i) { + ret += "."; + } + ret += std::to_string(version[i]); + } + return ret; + }; + LOG_COMPILER(ERROR) << "Load an file failed, an file version is incorrect, " + << "expected version is " << convToStr(AOTFileManager::AOT_VERSION) + << ", but got " << convToStr(anVersion); + file.close(); + return false; + } + + std::shared_ptr data = std::make_shared(AnFileData()); + loadedData_[filename] = data; + file.read(reinterpret_cast(&data->entryNum), sizeof(data->entryNum)); + data->entries.resize(data->entryNum); + file.read(reinterpret_cast(data->entries.data()), sizeof(AOTFileInfo::FuncEntryDes) * data->entryNum); + file.read(reinterpret_cast(&data->moduleNum), sizeof(data->moduleNum)); + data->des.resize(data->moduleNum); + file.read(reinterpret_cast(&data->totalCodeSize), sizeof(data->totalCodeSize)); + + int prot = PROT_READ | PROT_WRITE | PROT_EXEC; + auto pool = MemMapAllocator::GetInstance()->Allocate(AlignUp(data->totalCodeSize, 256_KB), 0, false, prot); + data->poolAddr = pool.GetMem(); + data->poolSize = pool.GetSize(); + + uint64_t codeAddress = reinterpret_cast(pool.GetMem()); + uint32_t curUnitOffset = 0; + for (size_t i = 0; i < data->moduleNum; i++) { + data->des[i].LoadSectionsInfo(file, curUnitOffset, codeAddress); + } + return true; +} + void AnFileInfo::Iterate(const RootVisitor &v) { v(Root::ROOT_VM, ObjectSlot(reinterpret_cast(&snapshotConstantPool_))); @@ -268,43 +375,19 @@ void AnFileInfo::RewriteRelcateTextSection([[maybe_unused]] const char* symbol, #endif } -bool AnFileInfo::Load(EcmaVM *vm, const std::string &filename) +bool AnFileInfo::Load(const std::string &filename) { - if (!VerifyFilePath(filename)) { - LOG_COMPILER(ERROR) << "Can not load aot file from path [ " << filename << " ], " - << "please execute ark_aot_compiler with options --aot-file."; - UNREACHABLE(); + AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance(); + if (!anFileDataManager->SafeLoad(filename)) { return false; } - std::ifstream file(filename.c_str(), std::ofstream::binary); - if (!file.good()) { - LOG_COMPILER(ERROR) << "Fail to load aot file: " << filename.c_str(); - file.close(); - return false; - } - std::array anVersion; - file.read(reinterpret_cast(anVersion.data()), sizeof(uint8_t) * AOTFileManager::AOT_VERSION_SIZE); - if (anVersion != vm->GetAOTFileManager()->AOT_VERSION) { - LOG_COMPILER(ERROR) << "Load aot file failed"; - file.close(); - return false; - } - file.read(reinterpret_cast(&entryNum_), sizeof(entryNum_)); - entries_.resize(entryNum_); - file.read(reinterpret_cast(entries_.data()), sizeof(FuncEntryDes) * entryNum_); - file.read(reinterpret_cast(&moduleNum_), sizeof(moduleNum_)); - des_.resize(moduleNum_); - uint32_t totalCodeSize = 0; - file.read(reinterpret_cast(&totalCodeSize), sizeof(totalCodeSize_)); - [[maybe_unused]] EcmaHandleScope handleScope(vm->GetAssociatedJSThread()); - int prot = PROT_READ | PROT_WRITE | PROT_EXEC; - auto pool = MemMapAllocator::GetInstance()->Allocate(AlignUp(totalCodeSize, 256_KB), 0, false, prot); - vm->GetAOTFileManager()->SetAOTmmap(pool.GetMem(), pool.GetSize()); - uint64_t codeAddress = reinterpret_cast(pool.GetMem()); - uint32_t curUnitOffset = 0; - for (size_t i = 0; i < moduleNum_; i++) { - des_[i].LoadSectionsInfo(file, curUnitOffset, codeAddress); - } + data_ = anFileDataManager->SafeGetAnFileData(ConvertToString(filename)); + entryNum_ = data_->entryNum; + entries_ = data_->entries; + moduleNum_ = data_->moduleNum; + totalCodeSize_ = data_->totalCodeSize; + des_ = data_->des; + for (size_t i = 0; i < entries_.size(); i++) { FuncEntryDes& funcDes = entries_[i]; auto moduleDes = des_[funcDes.moduleIndex_]; @@ -313,7 +396,7 @@ bool AnFileInfo::Load(EcmaVM *vm, const std::string &filename) mainEntryMap_[funcDes.indexInKindOrMethodId_] = funcDes.codeAddr_; } } - file.close(); + LOG_COMPILER(INFO) << "loaded aot file: " << filename.c_str(); isLoad_ = true; return true; @@ -329,14 +412,13 @@ bool AnFileInfo::IsLoadMain(const JSPandaFile *jsPandaFile, const CString &entry return true; } - void AOTFileInfo::Iterate(const RootVisitor &v) { v(Root::ROOT_VM, ObjectSlot(reinterpret_cast(&machineCodeObj_))); } bool AOTFileInfo::VerifyFilePath([[maybe_unused]] const std::string &filePath, - [[maybe_unused]] bool toGenerate) const + [[maybe_unused]] bool toGenerate) { #ifndef PANDA_TARGET_WINDOWS if (filePath.size() > PATH_MAX) { @@ -369,7 +451,7 @@ void AOTFileManager::LoadStubFile() void AOTFileManager::LoadAnFile(const std::string &fileName) { AnFileInfo anFileInfo_; - if (!anFileInfo_.Load(vm_, fileName)) { + if (!anFileInfo_.Load(fileName)) { return; } AddAnFileInfo(anFileInfo_); @@ -600,6 +682,12 @@ void AOTFileManager::AddSnapshotConstantPool(JSTaggedValue snapshotConstantPool) JSHandle AOTFileManager::GetSnapshotConstantPool(const JSPandaFile *jsPandaFile) { + // In some appilication, only the main vm will load '.an' file currently + // return the constantpool with HOLE value when other worker try to obtain the + // snapshot constantpool from aot_file_manager. + if (anFileInfos_.size() == 0) { + return JSHandle(vm_->GetJSThread(), JSTaggedValue::Hole()); + } uint32_t anFileInfoIndex = jsPandaFile->GetAOTFileInfoIndex(); const AnFileInfo &anFileInfo = anFileInfos_[anFileInfoIndex]; return anFileInfo.GetSnapshotConstantPool(); @@ -611,9 +699,6 @@ AOTFileManager::~AOTFileManager() delete arkStackMapParser_; arkStackMapParser_ = nullptr; } - for (size_t i = 0; i < aotAddrs_.size(); i++) { - MemMapAllocator::GetInstance()->Free(aotAddrs_[i].first, aotAddrs_[i].second, false); - } for (size_t i = 0; i < stubAddrs_.size(); i++) { MemMapAllocator::GetInstance()->Free(stubAddrs_[i].first, stubAddrs_[i].second, false); } diff --git a/ecmascript/aot_file_manager.h b/ecmascript/aot_file_manager.h index 674214529e..6abfffa94b 100644 --- a/ecmascript/aot_file_manager.h +++ b/ecmascript/aot_file_manager.h @@ -144,7 +144,8 @@ public: using CallSignature = kungfu::CallSignature; AOTFileInfo() = default; virtual ~AOTFileInfo() = default; - bool VerifyFilePath([[maybe_unused]] const std::string &filePath, [[maybe_unused]] bool toGenerate = false) const; + static bool VerifyFilePath([[maybe_unused]] const std::string &filePath, + [[maybe_unused]] bool toGenerate = false); struct FuncEntryDes { uint64_t codeAddr_; @@ -292,13 +293,41 @@ protected: JSTaggedValue machineCodeObj_ {JSTaggedValue::Hole()}; }; +class AnFileDataManager { +public: + static AnFileDataManager *GetInstance(); + + ~AnFileDataManager(); + + struct AnFileData { + uint32_t entryNum {0}; + uint32_t moduleNum {0}; + uint32_t totalCodeSize {0}; + std::vector entries {}; + std::vector des {}; + void *poolAddr {nullptr}; + size_t poolSize {0}; + }; + + bool SafeLoad(const std::string &filename); + std::shared_ptr SafeGetAnFileData(const CString &filename); + +private: + AnFileDataManager() = default; + std::shared_ptr UnsafeFind(const CString &filename) const; + bool UnsafeLoadData(const CString &filename); + + os::memory::RecursiveMutex lock_; + std::unordered_map, CStringHash> loadedData_; +}; + class PUBLIC_API AnFileInfo : public AOTFileInfo { public: AnFileInfo() = default; ~AnFileInfo() override = default; void Iterate(const RootVisitor &v); void Save(const std::string &filename); - bool Load(EcmaVM *vm, const std::string &filename); + bool Load(const std::string &filename); void AddModuleDes(ModuleSectionDes &moduleDes) { des_.emplace_back(moduleDes); @@ -343,6 +372,7 @@ private: void RewriteRelcateTextSection(const char* symbol, uintptr_t patchAddr); std::unordered_map mainEntryMap_ {}; JSTaggedValue snapshotConstantPool_ {JSTaggedValue::Hole()}; + std::shared_ptr data_; bool isLoad_ {false}; }; @@ -458,11 +488,6 @@ public: JSHandle GetSnapshotConstantPool(const JSPandaFile *jsPandaFile); private: - void SetAOTmmap(void *addr, size_t totalCodeSize) - { - aotAddrs_.emplace_back(std::make_pair(addr, totalCodeSize)); - } - void SetStubmmap(void *addr, size_t totalCodeSize) { stubAddrs_.emplace_back(std::make_pair(addr, totalCodeSize)); @@ -488,7 +513,6 @@ private: void AdjustBCStubAndDebuggerStubEntries(JSThread *thread, const std::vector &stubs, const AsmInterParsedOption &asmInterOpt); - std::vector> aotAddrs_; std::vector> stubAddrs_; EcmaVM *vm_ {nullptr}; ObjectFactory *factory_ {nullptr}; diff --git a/ecmascript/jspandafile/program_object.h b/ecmascript/jspandafile/program_object.h index 13ce30754b..246db7d1d9 100644 --- a/ecmascript/jspandafile/program_object.h +++ b/ecmascript/jspandafile/program_object.h @@ -74,7 +74,7 @@ public: LOG_ECMA_IF(mainIndex == nullptr, FATAL) << "Unknown methodId: " << id.GetOffset(); auto constpoolSize = mainIndex->method_idx_size; - JSHandle constpool; + JSHandle constpool(vm->GetJSThread(), JSTaggedValue::Hole()); bool isLoadedAOT = jsPandaFile->IsLoadedAOT(); if (isLoadedAOT) { #if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS) @@ -83,7 +83,8 @@ public: LOG_FULL(FATAL) << "Aot don't support Windows and MacOS platform"; UNREACHABLE(); #endif - } else { + } + if (constpool.GetTaggedValue().IsHole()) { ObjectFactory *factory = vm->GetFactory(); constpool = factory->NewConstantPool(constpoolSize); } From 1fdce1fc8e44fa7bbf06e0dd654ab577aae41ba1 Mon Sep 17 00:00:00 2001 From: wupengyong Date: Thu, 24 Nov 2022 15:55:30 +0800 Subject: [PATCH 13/14] reason:optimize for in description:optimize for in issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I62QDI?from=project-issue Signed-off-by: wupengyong Change-Id: I54fa0fa9401e5cfbd17db16705b58cb452474c89 --- ecmascript/dump.cpp | 6 +- ecmascript/js_api/js_api_arraylist.cpp | 13 +- ecmascript/js_api/js_api_arraylist.h | 1 + ecmascript/js_api/js_api_deque.cpp | 30 ++- ecmascript/js_api/js_api_deque.h | 2 + ecmascript/js_api/js_api_queue.cpp | 37 ++- ecmascript/js_api/js_api_queue.h | 1 + ecmascript/js_api/js_api_stack.cpp | 13 +- ecmascript/js_api/js_api_stack.h | 2 + ecmascript/js_api/js_api_vector.cpp | 13 +- ecmascript/js_api/js_api_vector.h | 1 + ecmascript/js_for_in_iterator.cpp | 221 +++++------------- ecmascript/js_for_in_iterator.h | 10 +- ecmascript/js_hclass.cpp | 1 + ecmascript/js_hclass.h | 16 ++ ecmascript/js_object.cpp | 67 ++++++ ecmascript/js_object.h | 6 + ecmascript/js_tagged_value.cpp | 52 +++++ ecmascript/js_tagged_value.h | 2 + ecmascript/js_typed_array.cpp | 36 +++ ecmascript/js_typed_array.h | 1 + ecmascript/module/js_module_namespace.cpp | 20 +- ecmascript/module/js_module_namespace.h | 2 + ecmascript/object_factory.cpp | 2 +- ecmascript/tagged_list.cpp | 5 +- ecmascript/tests/js_api_arraylist_test.cpp | 3 +- ecmascript/tests/js_api_deque_test.cpp | 3 +- ecmascript/tests/js_api_linked_list_test.cpp | 3 +- ecmascript/tests/js_api_list_test.cpp | 3 +- ecmascript/tests/js_api_queue_test.cpp | 3 +- ecmascript/tests/js_api_stack_test.cpp | 3 +- ecmascript/tests/js_api_vector_test.cpp | 5 +- test/moduletest/BUILD.gn | 3 + .../container/container_arraylist.js | 11 + test/moduletest/container/container_deque.js | 11 + test/moduletest/container/container_queue.js | 12 +- test/moduletest/container/container_stack.js | 11 + test/moduletest/container/container_vector.js | 11 + test/moduletest/forin/BUILD.gn | 18 ++ test/moduletest/forin/expect_output.txt | 28 +++ test/moduletest/forin/forin.js | 105 +++++++++ 41 files changed, 563 insertions(+), 230 deletions(-) create mode 100644 test/moduletest/forin/BUILD.gn create mode 100644 test/moduletest/forin/expect_output.txt create mode 100644 test/moduletest/forin/forin.js diff --git a/ecmascript/dump.cpp b/ecmascript/dump.cpp index 816bd41da3..bcb42a6fdb 100644 --- a/ecmascript/dump.cpp +++ b/ecmascript/dump.cpp @@ -1681,8 +1681,8 @@ void JSForInIterator::Dump(std::ostream &os) const os << "\n"; os << " - WasVisited : " << GetWasVisited(); os << "\n"; - os << " - VisitedKeys : "; - GetVisitedKeys().DumpTaggedValue(os); + os << " - VisitedObjs : "; + GetVisitedObjs().DumpTaggedValue(os); os << "\n"; os << " - RemainingKeys : "; GetRemainingKeys().DumpTaggedValue(os); @@ -4165,7 +4165,7 @@ void JSForInIterator::DumpForSnapshot(std::vector JSAPIArrayList::OwnKeys(JSThread *thread, const JSHandle &obj) { - uint32_t length = obj->GetLength().GetArrayLength(); - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - JSHandle keys = factory->NewTaggedArray(length); + return JSObject::GetOwnPropertyKeys(thread, JSHandle::Cast(obj)); +} - for (uint32_t i = 0; i < length; i++) { - keys->Set(thread, i, JSTaggedValue(i)); - } - - return keys; +JSHandle JSAPIArrayList::OwnEnumKeys(JSThread *thread, const JSHandle &obj) +{ + return JSObject::GetOwnEnumPropertyKeys(thread, JSHandle::Cast(obj)); } bool JSAPIArrayList::GetOwnProperty(JSThread *thread, const JSHandle &obj, diff --git a/ecmascript/js_api/js_api_arraylist.h b/ecmascript/js_api/js_api_arraylist.h index 6531991aaa..1bb99be184 100644 --- a/ecmascript/js_api/js_api_arraylist.h +++ b/ecmascript/js_api/js_api_arraylist.h @@ -69,6 +69,7 @@ public: bool Has(const JSTaggedValue value) const; static JSHandle OwnKeys(JSThread *thread, const JSHandle &obj); + static JSHandle OwnEnumKeys(JSThread *thread, const JSHandle &obj); static bool GetOwnProperty(JSThread *thread, const JSHandle &obj, const JSHandle &key); static OperationResult GetProperty(JSThread *thread, const JSHandle &obj, diff --git a/ecmascript/js_api/js_api_deque.cpp b/ecmascript/js_api/js_api_deque.cpp index 08b5e9b429..16b6f8845d 100644 --- a/ecmascript/js_api/js_api_deque.cpp +++ b/ecmascript/js_api/js_api_deque.cpp @@ -201,8 +201,6 @@ bool JSAPIDeque::Has(JSTaggedValue value) const JSHandle JSAPIDeque::OwnKeys(JSThread *thread, const JSHandle &deque) { uint32_t length = deque->GetSize(); - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - JSHandle keys = factory->NewTaggedArray(length); JSHandle oldElements(thread, deque->GetElements()); ASSERT(!oldElements->IsDictionaryMode()); @@ -210,18 +208,32 @@ JSHandle JSAPIDeque::OwnKeys(JSThread *thread, const JSHandleGetFirst(); uint32_t lastIndex = deque->GetLast(); - uint32_t size = deque->GetSize(); JSHandle newElements = - thread->GetEcmaVM()->GetFactory()->CopyDeque(oldElements, newCapacity, size, firstIndex, lastIndex); + thread->GetEcmaVM()->GetFactory()->CopyDeque(oldElements, newCapacity, length, firstIndex, lastIndex); deque->SetFirst(0); - deque->SetLast(size); + deque->SetLast(length); deque->SetElements(thread, newElements); - for (uint32_t i = 0; i < size; i++) { - keys->Set(thread, i, JSTaggedValue(i)); - } + return JSObject::GetOwnPropertyKeys(thread, JSHandle::Cast(deque)); +} - return keys; +JSHandle JSAPIDeque::OwnEnumKeys(JSThread *thread, const JSHandle &deque) +{ + uint32_t length = deque->GetSize(); + + JSHandle oldElements(thread, deque->GetElements()); + ASSERT(!oldElements->IsDictionaryMode()); + uint32_t oldCapacity = oldElements->GetLength(); + uint32_t newCapacity = ComputeCapacity(oldCapacity); + uint32_t firstIndex = deque->GetFirst(); + uint32_t lastIndex = deque->GetLast(); + JSHandle newElements = + thread->GetEcmaVM()->GetFactory()->CopyDeque(oldElements, newCapacity, length, firstIndex, lastIndex); + deque->SetFirst(0); + deque->SetLast(length); + deque->SetElements(thread, newElements); + + return JSObject::GetOwnEnumPropertyKeys(thread, JSHandle::Cast(deque)); } bool JSAPIDeque::GetOwnProperty(JSThread *thread, const JSHandle &deque, diff --git a/ecmascript/js_api/js_api_deque.h b/ecmascript/js_api/js_api_deque.h index c9a9270a2a..5043a2901e 100644 --- a/ecmascript/js_api/js_api_deque.h +++ b/ecmascript/js_api/js_api_deque.h @@ -49,6 +49,8 @@ public: static JSHandle OwnKeys(JSThread *thread, const JSHandle &deque); + static JSHandle OwnEnumKeys(JSThread *thread, const JSHandle &deque); + static bool GetOwnProperty(JSThread *thread, const JSHandle &deque, const JSHandle &key); static OperationResult GetProperty(JSThread *thread, const JSHandle &obj, const JSHandle &key); diff --git a/ecmascript/js_api/js_api_queue.cpp b/ecmascript/js_api/js_api_queue.cpp index 59aabd5fcd..efbf46c4a2 100644 --- a/ecmascript/js_api/js_api_queue.cpp +++ b/ecmascript/js_api/js_api_queue.cpp @@ -157,14 +157,39 @@ bool JSAPIQueue::Has(JSTaggedValue value) const JSHandle JSAPIQueue::OwnKeys(JSThread *thread, const JSHandle &obj) { uint32_t length = obj->GetLength().GetArrayLength(); - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - JSHandle keys = factory->NewTaggedArray(length); + + JSHandle oldElements(thread, obj->GetElements()); + ASSERT(!oldElements->IsDictionaryMode()); + uint32_t oldCapacity = oldElements->GetLength(); + uint32_t newCapacity = ComputeCapacity(oldCapacity); + uint32_t front = obj->GetFront(); + uint32_t tail = obj->GetTail(); + JSHandle newElements = + thread->GetEcmaVM()->GetFactory()->CopyQueue(oldElements, newCapacity, front, tail); + obj->SetFront(0); + obj->SetTail(length); + obj->SetElements(thread, newElements); - for (uint32_t i = 0; i < length; i++) { - keys->Set(thread, i, JSTaggedValue(i)); - } + return JSObject::GetOwnPropertyKeys(thread, JSHandle::Cast(obj)); +} - return keys; +JSHandle JSAPIQueue::OwnEnumKeys(JSThread *thread, const JSHandle &obj) +{ + uint32_t length = obj->GetLength().GetArrayLength(); + + JSHandle oldElements(thread, obj->GetElements()); + ASSERT(!oldElements->IsDictionaryMode()); + uint32_t oldCapacity = oldElements->GetLength(); + uint32_t newCapacity = ComputeCapacity(oldCapacity); + uint32_t front = obj->GetFront(); + uint32_t tail = obj->GetTail(); + JSHandle newElements = + thread->GetEcmaVM()->GetFactory()->CopyQueue(oldElements, newCapacity, front, tail); + obj->SetFront(0); + obj->SetTail(length); + obj->SetElements(thread, newElements); + + return JSObject::GetOwnEnumPropertyKeys(thread, JSHandle::Cast(obj)); } bool JSAPIQueue::GetOwnProperty(JSThread *thread, const JSHandle &obj, diff --git a/ecmascript/js_api/js_api_queue.h b/ecmascript/js_api/js_api_queue.h index 4fcf9b16d3..5c50321052 100644 --- a/ecmascript/js_api/js_api_queue.h +++ b/ecmascript/js_api/js_api_queue.h @@ -39,6 +39,7 @@ public: bool Has(JSTaggedValue value) const; static JSHandle OwnKeys(JSThread *thread, const JSHandle &obj); + static JSHandle OwnEnumKeys(JSThread *thread, const JSHandle &obj); static bool GetOwnProperty(JSThread *thread, const JSHandle &obj, const JSHandle &key); static OperationResult GetProperty(JSThread *thread, const JSHandle &obj, const JSHandle &key); diff --git a/ecmascript/js_api/js_api_stack.cpp b/ecmascript/js_api/js_api_stack.cpp index e9739ede2b..4a0dc93bb4 100644 --- a/ecmascript/js_api/js_api_stack.cpp +++ b/ecmascript/js_api/js_api_stack.cpp @@ -128,15 +128,12 @@ bool JSAPIStack::Has(JSTaggedValue value) const JSHandle JSAPIStack::OwnKeys(JSThread *thread, const JSHandle &obj) { - uint32_t top = static_cast(obj->GetTop()); - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - JSHandle keys = factory->NewTaggedArray(top + 1); + return JSObject::GetOwnPropertyKeys(thread, JSHandle::Cast(obj)); +} - for (uint32_t i = 0; i < top + 1; i++) { - keys->Set(thread, i, JSTaggedValue(i)); - } - - return keys; +JSHandle JSAPIStack::OwnEnumKeys(JSThread *thread, const JSHandle &obj) +{ + return JSObject::GetOwnEnumPropertyKeys(thread, JSHandle::Cast(obj)); } bool JSAPIStack::GetOwnProperty(JSThread *thread, const JSHandle &obj, diff --git a/ecmascript/js_api/js_api_stack.h b/ecmascript/js_api/js_api_stack.h index 9dcf9aa52c..d193847bd4 100644 --- a/ecmascript/js_api/js_api_stack.h +++ b/ecmascript/js_api/js_api_stack.h @@ -34,6 +34,8 @@ public: static JSHandle OwnKeys(JSThread *thread, const JSHandle &obj); + static JSHandle OwnEnumKeys(JSThread *thread, const JSHandle &obj); + static bool GetOwnProperty(JSThread *thread, const JSHandle &obj, const JSHandle &key); static OperationResult GetProperty(JSThread *thread, const JSHandle &obj, const JSHandle &key); diff --git a/ecmascript/js_api/js_api_vector.cpp b/ecmascript/js_api/js_api_vector.cpp index 8f14074668..15cef8420a 100644 --- a/ecmascript/js_api/js_api_vector.cpp +++ b/ecmascript/js_api/js_api_vector.cpp @@ -400,15 +400,12 @@ bool JSAPIVector::Has(const JSTaggedValue &value) const JSHandle JSAPIVector::OwnKeys(JSThread *thread, const JSHandle &obj) { - int32_t length = obj->GetSize(); - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - JSHandle keys = factory->NewTaggedArray(length); + return JSObject::GetOwnPropertyKeys(thread, JSHandle::Cast(obj)); +} - for (int32_t i = 0; i < length; i++) { - keys->Set(thread, i, JSTaggedValue(i)); - } - - return keys; +JSHandle JSAPIVector::OwnEnumKeys(JSThread *thread, const JSHandle &obj) +{ + return JSObject::GetOwnEnumPropertyKeys(thread, JSHandle::Cast(obj)); } bool JSAPIVector::GetOwnProperty(JSThread *thread, const JSHandle &obj, diff --git a/ecmascript/js_api/js_api_vector.h b/ecmascript/js_api/js_api_vector.h index f901c741a3..73df718e9e 100644 --- a/ecmascript/js_api/js_api_vector.h +++ b/ecmascript/js_api/js_api_vector.h @@ -83,6 +83,7 @@ public: bool Has(const JSTaggedValue &value) const; static JSHandle OwnKeys(JSThread *thread, const JSHandle &obj); + static JSHandle OwnEnumKeys(JSThread *thread, const JSHandle &obj); static bool GetOwnProperty(JSThread *thread, const JSHandle &obj, const JSHandle &key); static void TrimToCurrentLength(JSThread *thread, const JSHandle &vector); diff --git a/ecmascript/js_for_in_iterator.cpp b/ecmascript/js_for_in_iterator.cpp index c498de735d..060b8d0bfe 100644 --- a/ecmascript/js_for_in_iterator.cpp +++ b/ecmascript/js_for_in_iterator.cpp @@ -49,216 +49,99 @@ bool JSForInIterator::CheckObjProto(const JSThread *thread, const JSHandleGetObjectFunctionPrototypeClass().GetTaggedValue().GetTaggedObject()->GetClass(); } -void JSForInIterator::FastGetAllEnumKeys(const JSThread *thread, const JSHandle &it, - const JSHandle &object) +void JSForInIterator::GetAllEnumKeys(JSThread *thread, const JSHandle &it, + const JSHandle &object) { + ASSERT(object->IsHeapObject()); JSMutableHandle value(thread, JSTaggedValue::Undefined()); - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - JSHandle obj(object); - uint32_t numOfElements = obj->GetNumberOfElements(); - uint32_t numOfKeys = obj->GetNumberOfKeys(); - JSHandle remaining = factory->NewTaggedQueue(numOfElements + numOfKeys + 1); - if (numOfElements > 0) { - uint32_t elementIndex = 0; - if (obj->IsJSPrimitiveRef() && JSPrimitiveRef::Cast(*obj)->IsString()) { - elementIndex = JSPrimitiveRef::Cast(*obj)->GetStringLength(); - for (uint32_t i = 0; i < elementIndex; i++) { - value.Update(factory->NewFromASCII(ToCString(i)).GetTaggedValue()); - TaggedQueue::PushFixedQueue(thread, remaining, value); + JSMutableHandle remaining(thread, thread->GlobalConstants()->GetEmptyTaggedQueue()); + if (object->IsJSProxy()) { + JSHandle proxyArr = JSProxy::OwnPropertyKeys(thread, JSHandle(object)); + uint32_t length = proxyArr->GetLength(); + for (uint32_t i = 0; i < length; i++) { + value.Update(proxyArr->Get(i)); + PropertyDescriptor desc(thread); + JSProxy::GetOwnProperty(thread, JSHandle(object), value, desc); + if (desc.IsEnumerable()) { + TaggedQueue *newQueue = TaggedQueue::Push(thread, remaining, value); + remaining.Update(JSTaggedValue(newQueue)); } - } else { - JSHandle elements(thread, obj->GetElements()); - if (!elements->IsDictionaryMode()) { - uint32_t elementsLen = elements->GetLength(); - for (uint32_t i = 0; i < elementsLen; ++i) { - if (!elements->Get(i).IsHole()) { - value.Update(factory->NewFromASCII(ToCString(i)).GetTaggedValue()); - TaggedQueue::PushFixedQueue(thread, remaining, value); - } - } - } else { - JSHandle numberDic(elements); - int size = numberDic->Size(); - CVector sortArr; - for (int hashIndex = 0; hashIndex < size; hashIndex++) { - JSTaggedValue key = numberDic->GetKey(hashIndex); - if (!key.IsUndefined() && !key.IsHole()) { - PropertyAttributes attr = numberDic->GetAttributes(hashIndex); - if (attr.IsEnumerable()) { - sortArr.push_back(JSTaggedValue(static_cast(key.GetInt()))); - } - } - } - std::sort(sortArr.begin(), sortArr.end(), NumberDictionary::CompKey); - for (const auto &entry : sortArr) { - value.Update(factory->NewFromASCII(ToCString(entry.GetInt())).GetTaggedValue()); - TaggedQueue::PushFixedQueue(thread, remaining, value); - } + } + } else { + JSHandle arr = JSTaggedValue::GetOwnEnumPropertyKeys(thread, object); + uint32_t len = arr->GetLength(); + for (uint32_t i = 0; i < len; i++) { + value.Update(arr->Get(i)); + if (value->IsString()) { + TaggedQueue *newQueue = TaggedQueue::Push(thread, remaining, value); + remaining.Update(JSTaggedValue(newQueue)); } } } - if (numOfKeys > 0) { - if (obj->IsJSGlobalObject()) { - GlobalDictionary *dict = GlobalDictionary::Cast(obj->GetProperties().GetTaggedObject()); - int size = dict->Size(); - CVector> sortArr; - for (int hashIndex = 0; hashIndex < size; hashIndex++) { - JSTaggedValue key = dict->GetKey(hashIndex); - if (!key.IsUndefined() && !key.IsHole()) { - PropertyAttributes attr = dict->GetAttributes(hashIndex); - if (attr.IsEnumerable()) { - std::pair pair(key, attr.GetOffset()); - sortArr.emplace_back(pair); - } + if (it->GetHasVisitObjs()) { + JSMutableHandle remained(thread, thread->GlobalConstants()->GetEmptyTaggedQueue()); + JSMutableHandle visited(thread, it->GetVisitedObjs()); + uint32_t size = visited->Size(); + while (!remaining->Empty()) { + JSHandle key(thread, remaining->Pop(thread)); + bool has = false; + for (uint32_t i = 0; i < size; i++) { + value.Update(visited->Get(i)); + PropertyDescriptor desc(thread); + has = JSTaggedValue::GetOwnProperty(thread, value, key, desc); + if (has) { + break; } } - std::sort(sortArr.begin(), sortArr.end(), GlobalDictionary::CompKey); - for (const auto &entry : sortArr) { - JSTaggedValue nameKey = entry.first; - if (nameKey.IsString()) { - value.Update(nameKey); - TaggedQueue::PushFixedQueue(thread, remaining, value); - } - } - } else { - JSHandle propertiesArr(thread, obj->GetProperties()); - if (!propertiesArr->IsDictionaryMode()) { - JSHClass *jsHclass = obj->GetJSHClass(); - JSTaggedValue enumCache = jsHclass->GetEnumCache(); - if (!enumCache.IsNull()) { - JSHandle cache(thread, enumCache); - uint32_t length = cache->GetLength(); - if (length != numOfKeys) { - JSHandle layoutInfoHandle(thread, jsHclass->GetLayout()); - for (uint32_t i = 0; i < numOfKeys; i++) { - JSTaggedValue key = layoutInfoHandle->GetKey(i); - if (key.IsString()) { - value.Update(key); - if (layoutInfoHandle->GetAttr(i).IsEnumerable()) { - TaggedQueue::PushFixedQueue(thread, remaining, value); - } - } - } - } else { - for (uint32_t i = 0; i < length; i++) { - JSTaggedValue key = cache->Get(i); - if (key.IsString()) { - value.Update(key); - TaggedQueue::PushFixedQueue(thread, remaining, value); - } - } - } - } else { - JSHandle layoutInfoHandle(thread, jsHclass->GetLayout()); - for (uint32_t i = 0; i < numOfKeys; i++) { - JSTaggedValue key = layoutInfoHandle->GetKey(i); - if (key.IsString()) { - value.Update(key); - if (layoutInfoHandle->GetAttr(i).IsEnumerable()) { - TaggedQueue::PushFixedQueue(thread, remaining, value); - } - } - } - } - } else { - JSHandle nameDic(propertiesArr); - int size = nameDic->Size(); - CVector> sortArr; - for (int hashIndex = 0; hashIndex < size; hashIndex++) { - JSTaggedValue key = nameDic->GetKey(hashIndex); - if (key.IsString()) { - PropertyAttributes attr = nameDic->GetAttributes(hashIndex); - if (attr.IsEnumerable()) { - std::pair pair(key, attr); - sortArr.emplace_back(pair); - } - } - } - std::sort(sortArr.begin(), sortArr.end(), NameDictionary::CompKey); - for (const auto &entry : sortArr) { - value.Update(entry.first); - TaggedQueue::PushFixedQueue(thread, remaining, value); - } + if (!has) { + TaggedQueue *newQueue = TaggedQueue::Push(thread, remained, key); + remained.Update(JSTaggedValue(newQueue)); } } + it->SetRemainingKeys(thread, remained); + } else { + it->SetRemainingKeys(thread, remaining); } - it->SetRemainingKeys(thread, remaining); - it->SetWasVisited(true); -} - -void JSForInIterator::SlowGetAllEnumKeys(JSThread *thread, const JSHandle &it, - const JSHandle &object) -{ - JSMutableHandle visited(thread, it->GetVisitedKeys()); - JSMutableHandle value(thread, JSTaggedValue::Undefined()); - JSMutableHandle remaining(thread, it->GetRemainingKeys()); - JSHandle arr = JSTaggedValue::GetOwnPropertyKeys(thread, object); - uint32_t len = arr->GetLength(); - for (uint32_t i = 0; i < len; i++) { - value.Update(arr->Get(i)); - if (value->IsString()) { - TaggedQueue *newQueue = TaggedQueue::Push(thread, remaining, value); - remaining.Update(JSTaggedValue(newQueue)); - } - } - it->SetRemainingKeys(thread, remaining); - it->SetVisitedKeys(thread, visited); it->SetWasVisited(true); + object->GetTaggedObject()->GetClass()->SetHasDeleteProperty(false); } std::pair JSForInIterator::NextInternal(JSThread *thread, const JSHandle &it) { - bool notModiObjProto = true; - notModiObjProto = CheckObjProto(thread, it); while (true) { JSHandle object(thread, it->GetObject()); if (object->IsNull() || object->IsUndefined()) { return std::make_pair(JSTaggedValue::Undefined(), true); } if (!it->GetWasVisited()) { - if (object->IsJSObject() && notModiObjProto) { - FastGetAllEnumKeys(thread, it, object); - } else { - SlowGetAllEnumKeys(thread, it, object); - } + GetAllEnumKeys(thread, it, object); } JSHandle remaining(thread, it->GetRemainingKeys()); - JSMutableHandle visited(thread, it->GetVisitedKeys()); while (!remaining->Empty()) { + ASSERT(object->IsHeapObject()); JSTaggedValue r = remaining->Pop(thread); - if (object->IsJSObject() && notModiObjProto) { + bool hasDelete = object->GetTaggedObject()->GetClass()->HasDeleteProperty(); + if (object->IsJSObject() && !hasDelete) { return std::make_pair(r, false); } JSHandle key(thread, r); - bool has_same = false; - uint32_t len = visited->Size(); - for (uint32_t i = 0; i < len; i++) { - if (JSTaggedValue::SameValue(r, visited->Get(i))) { - has_same = true; - break; - } - } - if (has_same) { - continue; - } PropertyDescriptor desc(thread); bool has = JSTaggedValue::GetOwnProperty(thread, object, key, desc); if (has) { - auto newQueue = JSTaggedValue(TaggedQueue::Push(thread, visited, key)); - visited.Update(newQueue); - it->SetVisitedKeys(thread, newQueue); if (desc.IsEnumerable()) { return std::make_pair(key.GetTaggedValue(), false); } } } - if (notModiObjProto) { - return std::make_pair(JSTaggedValue::Undefined(), true); - } + JSMutableHandle visited(thread, it->GetVisitedObjs()); + TaggedQueue *newQueue = TaggedQueue::Push(thread, visited, object); + visited.Update(JSTaggedValue(newQueue)); + it->SetVisitedObjs(thread, visited); JSTaggedValue proto = JSTaggedValue::GetPrototype(thread, object); it->SetObject(thread, proto); it->SetWasVisited(false); + it->SetHasVisitObjs(true); } } diff --git a/ecmascript/js_for_in_iterator.h b/ecmascript/js_for_in_iterator.h index 89fcfc0a5c..08a0b16ab1 100644 --- a/ecmascript/js_for_in_iterator.h +++ b/ecmascript/js_for_in_iterator.h @@ -33,15 +33,12 @@ public: static bool CheckObjProto(const JSThread *thread, const JSHandle &it); - static void FastGetAllEnumKeys(const JSThread *thread, const JSHandle &it, - const JSHandle &object); - - static void SlowGetAllEnumKeys(JSThread *thread, const JSHandle &it, - const JSHandle &object); + static void GetAllEnumKeys(JSThread *thread, const JSHandle &it, + const JSHandle &object); static constexpr size_t OBJECT_OFFSET = JSObject::SIZE; ACCESSORS(Object, OBJECT_OFFSET, VISITED_KEYS_OFFSET) - ACCESSORS(VisitedKeys, VISITED_KEYS_OFFSET, REMAINING_KEYS_OFFSET) + ACCESSORS(VisitedObjs, VISITED_KEYS_OFFSET, REMAINING_KEYS_OFFSET) ACCESSORS(RemainingKeys, REMAINING_KEYS_OFFSET, BIT_FIELD_OFFSET) ACCESSORS_BIT_FIELD(BitField, BIT_FIELD_OFFSET, LAST_OFFSET) DEFINE_ALIGN_SIZE(LAST_OFFSET); @@ -49,6 +46,7 @@ public: // define BitField static constexpr size_t WAS_VISITED_BITS = 3; FIRST_BIT_FIELD(BitField, WasVisited, bool, WAS_VISITED_BITS) + NEXT_BIT_FIELD(BitField, HasVisitObjs, bool, 1, WasVisited) DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, OBJECT_OFFSET, BIT_FIELD_OFFSET) DECL_DUMP() diff --git a/ecmascript/js_hclass.cpp b/ecmascript/js_hclass.cpp index 3b260f74df..0053dca374 100644 --- a/ecmascript/js_hclass.cpp +++ b/ecmascript/js_hclass.cpp @@ -137,6 +137,7 @@ void JSHClass::Initialize(const JSThread *thread, uint32_t size, JSType type, ui SetObjectType(type); SetExtensible(true); SetIsPrototype(false); + SetHasDeleteProperty(false); SetElementRepresentation(Representation::NONE); SetTransitions(thread, JSTaggedValue::Undefined()); SetProtoChangeMarker(thread, JSTaggedValue::Null()); diff --git a/ecmascript/js_hclass.h b/ecmascript/js_hclass.h index 3c312031b3..2447afc323 100644 --- a/ecmascript/js_hclass.h +++ b/ecmascript/js_hclass.h @@ -303,6 +303,7 @@ public: using InlinedPropsStartBits = NumberOfPropsBits::NextField; // 15 using ObjectSizeInWordsBits = InlinedPropsStartBits::NextField; // 30 + using HasDeletePropertyBit = ObjectSizeInWordsBits::NextFlag; static JSHClass *Cast(const TaggedObject *object); @@ -1486,6 +1487,16 @@ public: } } + inline void SetHasDeleteProperty(bool flag) const + { + HasDeletePropertyBit::Set(flag, GetBitField1Addr()); + } + + inline bool HasDeleteProperty() const + { + uint32_t bits = GetBitField1(); + return HasDeletePropertyBit::Decode(bits); + } static constexpr size_t PROTOTYPE_OFFSET = TaggedObjectSize(); ACCESSORS(Proto, PROTOTYPE_OFFSET, LAYOUT_OFFSET); ACCESSORS(Layout, LAYOUT_OFFSET, TRANSTIONS_OFFSET); @@ -1529,6 +1540,11 @@ private: { return reinterpret_cast(ToUintPtr(this) + BIT_FIELD_OFFSET); } + + uint32_t *GetBitField1Addr() const + { + return reinterpret_cast(ToUintPtr(this) + BIT_FIELD1_OFFSET); + } friend class RuntimeStubs; }; static_assert(JSHClass::BIT_FIELD_OFFSET % static_cast(MemAlignment::MEM_ALIGN_OBJECT) == 0); diff --git a/ecmascript/js_object.cpp b/ecmascript/js_object.cpp index 90d365e03a..d2a6f92ecd 100644 --- a/ecmascript/js_object.cpp +++ b/ecmascript/js_object.cpp @@ -377,6 +377,30 @@ JSHandle JSObject::GetAllEnumKeys(const JSThread *thread, const JSH return keyArray; } +void JSObject::GetAllEnumKeys(const JSThread *thread, const JSHandle &obj, int offset, + const JSHandle &keyArray) +{ + TaggedArray *array = TaggedArray::Cast(obj->GetProperties().GetTaggedObject()); + uint32_t keys = 0; + if (!array->IsDictionaryMode()) { + JSHClass *jsHclass = obj->GetJSHClass(); + int end = static_cast(jsHclass->NumberOfProps()); + if (end > 0) { + LayoutInfo::Cast(jsHclass->GetLayout().GetTaggedObject()) + ->GetAllEnumKeys(thread, end, offset, *keyArray, &keys, obj); + } + return; + } + if (obj->IsJSGlobalObject()) { + GlobalDictionary *dict = GlobalDictionary::Cast(obj->GetProperties().GetTaggedObject()); + dict->GetEnumAllKeys(thread, offset, *keyArray, &keys); + return; + } + + NameDictionary *dict = NameDictionary::Cast(obj->GetProperties().GetTaggedObject()); + dict->GetAllEnumKeys(thread, offset, *keyArray, &keys); +} + void JSObject::GetAllElementKeys(JSThread *thread, const JSHandle &obj, int offset, const JSHandle &keyArray) { @@ -457,6 +481,33 @@ JSHandle JSObject::GetEnumElementKeys(JSThread *thread, const JSHan return elementArray; } +void JSObject::GetEnumElementKeys(JSThread *thread, const JSHandle &obj, int offset, + const JSHandle &keyArray) +{ + uint32_t elementIndex = 0; + if (obj->IsJSPrimitiveRef() && JSPrimitiveRef::Cast(*obj)->IsString()) { + elementIndex = JSPrimitiveRef::Cast(*obj)->GetStringLength() + static_cast(offset); + for (uint32_t i = static_cast(offset); i < elementIndex; ++i) { + auto key = base::NumberHelper::NumberToString(thread, JSTaggedValue(i)); + keyArray->Set(thread, i, key); + } + } + + JSHandle elements(thread, obj->GetElements()); + if (!elements->IsDictionaryMode()) { + uint32_t elementsLen = elements->GetLength(); + for (uint32_t i = 0, j = elementIndex; i < elementsLen; ++i) { + if (!elements->Get(i).IsHole()) { + auto key = base::NumberHelper::NumberToString(thread, JSTaggedValue(i)); + keyArray->Set(thread, j++, key); + } + } + } else { + uint32_t keys = 0; + NumberDictionary::GetAllEnumKeys(thread, JSHandle(elements), elementIndex, keyArray, &keys); + } +} + uint32_t JSObject::GetNumberOfKeys() { DISALLOW_GARBAGE_COLLECTION; @@ -805,6 +856,7 @@ bool JSObject::DeleteProperty(JSThread *thread, const JSHandle &obj, c // 6. Return false. if (op.IsConfigurable()) { op.DeletePropertyInHolder(); + obj->GetClass()->SetHasDeleteProperty(true); return true; } return false; @@ -1123,6 +1175,21 @@ JSHandle JSObject::GetOwnPropertyKeys(JSThread *thread, const JSHan return keyArray; } +JSHandle JSObject::GetOwnEnumPropertyKeys(JSThread *thread, const JSHandle &obj) +{ + [[maybe_unused]] uint32_t elementIndex = 0; + uint32_t numOfElements = obj->GetNumberOfElements(); + uint32_t keyLen = numOfElements + obj->GetNumberOfKeys(); + + JSHandle keyArray = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(keyLen); + + if (numOfElements > 0) { + GetEnumElementKeys(thread, obj, 0, keyArray); + } + GetAllEnumKeys(thread, obj, static_cast(numOfElements), keyArray); + return keyArray; +} + JSHandle JSObject::ObjectCreate(JSThread *thread, const JSHandle &proto) { JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); diff --git a/ecmascript/js_object.h b/ecmascript/js_object.h index 496b23d741..d58b9cea19 100644 --- a/ecmascript/js_object.h +++ b/ecmascript/js_object.h @@ -500,6 +500,8 @@ public: // [[OwnPropertyKeys]] static JSHandle GetOwnPropertyKeys(JSThread *thread, const JSHandle &obj); + static JSHandle GetOwnEnumPropertyKeys(JSThread *thread, const JSHandle &obj); + // 9.1.13 ObjectCreate static JSHandle ObjectCreate(JSThread *thread, const JSHandle &proto); @@ -575,8 +577,12 @@ public: static JSHandle GetEnumElementKeys(JSThread *thread, const JSHandle &obj, int offset, uint32_t numOfElements, uint32_t *keys); + static void GetEnumElementKeys(JSThread *thread, const JSHandle &obj, int offset, + const JSHandle &keyArray); static JSHandle GetAllEnumKeys(const JSThread *thread, const JSHandle &obj, int offset, uint32_t numOfKeys, uint32_t *keys); + static void GetAllEnumKeys(const JSThread *thread, const JSHandle &obj, int offset, + const JSHandle &keyArray); static void AddAccessor(JSThread *thread, const JSHandle &obj, const JSHandle &key, const JSHandle &value, PropertyAttributes attr); diff --git a/ecmascript/js_tagged_value.cpp b/ecmascript/js_tagged_value.cpp index 55d3ab90e0..94e8c2b357 100644 --- a/ecmascript/js_tagged_value.cpp +++ b/ecmascript/js_tagged_value.cpp @@ -845,6 +845,21 @@ JSHandle JSTaggedValue::GetOwnPropertyKeys(JSThread *thread, const return JSObject::GetOwnPropertyKeys(thread, JSHandle(obj)); } +JSHandle JSTaggedValue::GetOwnEnumPropertyKeys(JSThread *thread, const JSHandle &obj) +{ + ASSERT(!obj->IsJSProxy()); + if (obj->IsTypedArray()) { + return JSTypedArray::OwnEnumPropertyKeys(thread, obj); + } + if (obj->IsSpecialContainer()) { + return GetOwnContainerEnumPropertyKeys(thread, obj); + } + if (obj->IsModuleNamespace()) { + return ModuleNamespace::OwnEnumPropertyKeys(thread, obj); + } + return JSObject::GetOwnEnumPropertyKeys(thread, JSHandle(obj)); +} + // 7.3.10 HasProperty (O, P) bool JSTaggedValue::HasProperty(JSThread *thread, const JSHandle &obj, const JSHandle &key) @@ -1047,6 +1062,43 @@ JSHandle JSTaggedValue::GetOwnContainerPropertyKeys(JSThread *threa return thread->GetEcmaVM()->GetFactory()->EmptyArray(); } +JSHandle JSTaggedValue::GetOwnContainerEnumPropertyKeys(JSThread *thread, + const JSHandle &obj) +{ + auto *hclass = obj->GetTaggedObject()->GetClass(); + JSType jsType = hclass->GetObjectType(); + switch (jsType) { + case JSType::JS_API_QUEUE: { + return JSAPIQueue::OwnEnumKeys(thread, JSHandle::Cast(obj)); + } + case JSType::JS_API_DEQUE: { + return JSAPIDeque::OwnEnumKeys(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_VECTOR: + case JSType::JS_API_STACK: + case JSType::JS_API_ARRAY_LIST: + case JSType::JS_API_PLAIN_ARRAY: + case JSType::JS_API_HASH_MAP: + case JSType::JS_API_HASH_SET: + case JSType::JS_API_LIGHT_WEIGHT_MAP: + case JSType::JS_API_LIGHT_WEIGHT_SET: + case JSType::JS_API_TREE_MAP: + case JSType::JS_API_TREE_SET: { + return JSObject::GetOwnEnumPropertyKeys(thread, JSHandle(obj)); + } + default: { + UNREACHABLE(); + } + } + return thread->GetEcmaVM()->GetFactory()->EmptyArray(); +} + bool JSTaggedValue::GetContainerProperty(JSThread *thread, const JSHandle &obj, const JSHandle &key, PropertyDescriptor &desc) { diff --git a/ecmascript/js_tagged_value.h b/ecmascript/js_tagged_value.h index 193eabd56f..ca7c744793 100644 --- a/ecmascript/js_tagged_value.h +++ b/ecmascript/js_tagged_value.h @@ -477,6 +477,7 @@ public: static JSTaggedValue GetPrototype(JSThread *thread, const JSHandle &obj); static bool PreventExtensions(JSThread *thread, const JSHandle &obj); static JSHandle GetOwnPropertyKeys(JSThread *thread, const JSHandle &obj); + static JSHandle GetOwnEnumPropertyKeys(JSThread *thread, const JSHandle &obj); static bool HasProperty(JSThread *thread, const JSHandle &obj, const JSHandle &key); static bool HasProperty(JSThread *thread, const JSHandle &obj, uint32_t key); static bool HasOwnProperty(JSThread *thread, const JSHandle &obj, @@ -692,6 +693,7 @@ private: static bool HasContainerProperty(JSThread *thread, const JSHandle &obj, const JSHandle &key); static JSHandle GetOwnContainerPropertyKeys(JSThread *thread, const JSHandle &obj); + static JSHandle GetOwnContainerEnumPropertyKeys(JSThread *thread, const JSHandle &obj); static bool GetContainerProperty(JSThread *thread, const JSHandle &obj, const JSHandle &key, PropertyDescriptor &desc); static OperationResult GetJSAPIProperty(JSThread *thread, const JSHandle &obj, diff --git a/ecmascript/js_typed_array.cpp b/ecmascript/js_typed_array.cpp index a55402fcfa..3c3f03f8de 100644 --- a/ecmascript/js_typed_array.cpp +++ b/ecmascript/js_typed_array.cpp @@ -322,6 +322,42 @@ JSHandle JSTypedArray::OwnPropertyKeys(JSThread *thread, const JSHa return factory->CopyArray(nameList, length, copyLength); } +JSHandle JSTypedArray::OwnEnumPropertyKeys(JSThread *thread, const JSHandle &typedarray) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + // 1. Let keys be a new empty List. + // 2. Assert: O is an Object that has [[ViewedArrayBuffer]], [[ArrayLength]], [[ByteOffset]], and + // [[TypedArrayName]] internal slots. + // 3. Let len be the value of O’s [[ArrayLength]] internal slot. + JSHandle arrayObj(typedarray); + JSHandle objKeys = JSObject::GetOwnEnumPropertyKeys(thread, JSHandle::Cast(arrayObj)); + uint32_t objKeysLen = objKeys->GetLength(); + uint32_t bufferKeysLen = arrayObj->GetArrayLength(); + uint32_t length = objKeysLen + bufferKeysLen; + JSHandle nameList = factory->NewTaggedArray(length); + + // 4. For each integer i starting with 0 such that i < len, in ascending order, + // a. Add ToString(i) as the last element of keys. + uint32_t copyLength = 0; + for (uint32_t k = 0; k < bufferKeysLen; k++) { + auto key = base::NumberHelper::NumberToString(thread, JSTaggedValue(k)); + nameList->Set(thread, copyLength, key); + copyLength++; + } + + // 5. For each own property key P of O such that Type(P) is String and P is not an integer index, in + // property creation order + // a. Add P as the last element of keys. + for (uint32_t i = 0; i < objKeysLen; i++) { + JSTaggedValue key = objKeys->Get(i); + nameList->Set(thread, copyLength, key); + copyLength++; + } + + // 7. Return keys. + return factory->CopyArray(nameList, length, copyLength); +} + // 9.4.5.7 IntegerIndexedObjectCreate (prototype, internalSlotsList) // 9.4.5.8 IntegerIndexedElementGet ( O, index ) diff --git a/ecmascript/js_typed_array.h b/ecmascript/js_typed_array.h index 57166d4a5e..ce5a6bde3b 100644 --- a/ecmascript/js_typed_array.h +++ b/ecmascript/js_typed_array.h @@ -77,6 +77,7 @@ public: const JSHandle &key); // 9.4.5.6 [[OwnPropertyKeys]] ( ) static JSHandle OwnPropertyKeys(JSThread *thread, const JSHandle &typedarray); + static JSHandle OwnEnumPropertyKeys(JSThread *thread, const JSHandle &typedarray); // 9.4.5.7 IntegerIndexedObjectCreate (prototype, internalSlotsList) // 9.4.5.8 IntegerIndexedElementGet ( O, index ) static OperationResult IntegerIndexedElementGet(JSThread *thread, const JSHandle &typedarray, diff --git a/ecmascript/module/js_module_namespace.cpp b/ecmascript/module/js_module_namespace.cpp index b3262fbdc3..7ab72a2a90 100644 --- a/ecmascript/module/js_module_namespace.cpp +++ b/ecmascript/module/js_module_namespace.cpp @@ -108,7 +108,6 @@ OperationResult ModuleNamespace::GetProperty(JSThread *thread, const JSHandle ModuleNamespace::OwnPropertyKeys(JSThread *thread, const JSHandle &obj) { ASSERT(obj->IsModuleNamespace()); @@ -128,6 +127,25 @@ JSHandle ModuleNamespace::OwnPropertyKeys(JSThread *thread, const J return result; } +JSHandle ModuleNamespace::OwnEnumPropertyKeys(JSThread *thread, const JSHandle &obj) +{ + ASSERT(obj->IsModuleNamespace()); + // 1. Let exports be a copy of O.[[Exports]]. + JSHandle moduleNamespace = JSHandle::Cast(obj); + JSHandle exports(thread, moduleNamespace->GetExports()); + JSHandle exportsArray = JSArray::ToTaggedArray(thread, exports); + if (!moduleNamespace->ValidateKeysAvailable(thread, exportsArray)) { + return exportsArray; + } + + // 2. Let symbolKeys be ! OrdinaryOwnPropertyKeys(O). + JSHandle symbolKeys = JSObject::GetOwnEnumPropertyKeys(thread, JSHandle(obj)); + // 3. Append all the entries of symbolKeys to the end of exports. + JSHandle result = TaggedArray::Append(thread, exportsArray, symbolKeys); + // 4. Return exports. + return result; +} + bool ModuleNamespace::PreventExtensions() { return true; diff --git a/ecmascript/module/js_module_namespace.h b/ecmascript/module/js_module_namespace.h index d7ccedf72a..3154484de5 100644 --- a/ecmascript/module/js_module_namespace.h +++ b/ecmascript/module/js_module_namespace.h @@ -51,6 +51,8 @@ public: // 9.4.6.10[[OwnPropertyKeys]] static JSHandle OwnPropertyKeys(JSThread *thread, const JSHandle &proxy); + static JSHandle OwnEnumPropertyKeys(JSThread *thread, const JSHandle &obj); + bool ValidateKeysAvailable(JSThread *thread, const JSHandle &exports); static constexpr size_t MODULE_OFFSET = JSObject::SIZE; diff --git a/ecmascript/object_factory.cpp b/ecmascript/object_factory.cpp index ba24b1268f..a31482c454 100644 --- a/ecmascript/object_factory.cpp +++ b/ecmascript/object_factory.cpp @@ -639,7 +639,7 @@ JSHandle ObjectFactory::NewJSForinIterator(const JSHandle it = JSHandle::Cast(NewJSObject(hclass)); it->SetObject(thread_, obj); - it->SetVisitedKeys(thread_, thread_->GlobalConstants()->GetEmptyTaggedQueue()); + it->SetVisitedObjs(thread_, thread_->GlobalConstants()->GetEmptyTaggedQueue()); it->SetRemainingKeys(thread_, thread_->GlobalConstants()->GetEmptyTaggedQueue()); it->ClearBitField(); return it; diff --git a/ecmascript/tagged_list.cpp b/ecmascript/tagged_list.cpp index 1e9c04dcfd..eaf1ad2308 100644 --- a/ecmascript/tagged_list.cpp +++ b/ecmascript/tagged_list.cpp @@ -130,10 +130,9 @@ JSHandle TaggedList::OwnKeys(JSThread *thread, const JSHan JSHandle keys = factory->NewTaggedArray(length); for (uint32_t i = 0; i < length; i++) { - JSTaggedValue elementData = JSTaggedValue(i); - keys->Set(thread, i, elementData); + auto key = base::NumberHelper::NumberToString(thread, JSTaggedValue(i)); + keys->Set(thread, i, key); } - return keys; } diff --git a/ecmascript/tests/js_api_arraylist_test.cpp b/ecmascript/tests/js_api_arraylist_test.cpp index b3b212cbbd..c254a09cb5 100644 --- a/ecmascript/tests/js_api_arraylist_test.cpp +++ b/ecmascript/tests/js_api_arraylist_test.cpp @@ -631,7 +631,8 @@ HWTEST_F_L0(JSAPIArrayListTest, OwnKeys) JSHandle keys = JSAPIArrayList::OwnKeys(thread, arrayList); uint32_t length = arrayList->GetLength().GetArrayLength(); for (uint32_t i = 0; i < length; i++) { - EXPECT_EQ(keys->Get(i), JSTaggedValue(i)); + ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))), + EcmaString::Cast(keys->Get(i).GetTaggedObject()))); } } diff --git a/ecmascript/tests/js_api_deque_test.cpp b/ecmascript/tests/js_api_deque_test.cpp index 69d64e6a70..bb78716b72 100644 --- a/ecmascript/tests/js_api_deque_test.cpp +++ b/ecmascript/tests/js_api_deque_test.cpp @@ -278,7 +278,8 @@ HWTEST_F_L0(JSAPIDequeTest, OwnKeys) EXPECT_TRUE(keyArray->GetClass()->IsTaggedArray()); EXPECT_TRUE(keyArray->GetLength() == elementsNums); for (uint32_t i = 0; i < elementsNums; i++) { - EXPECT_EQ(keyArray->Get(i), toor->Get(i)); + ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))), + EcmaString::Cast(keyArray->Get(i).GetTaggedObject()))); } } } // namespace panda::test diff --git a/ecmascript/tests/js_api_linked_list_test.cpp b/ecmascript/tests/js_api_linked_list_test.cpp index 07fe84b66a..1b40da64e4 100644 --- a/ecmascript/tests/js_api_linked_list_test.cpp +++ b/ecmascript/tests/js_api_linked_list_test.cpp @@ -440,7 +440,8 @@ HWTEST_F_L0(JSAPILinkedListTest, OwnKeys) EXPECT_TRUE(keyArray->GetClass()->IsTaggedArray()); EXPECT_TRUE(keyArray->GetLength() == elementsNums); for (uint32_t i = 0; i < elementsNums; i++) { - EXPECT_EQ(keyArray->Get(i), JSTaggedValue(i)); + ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))), + EcmaString::Cast(keyArray->Get(i).GetTaggedObject()))); } } } // namespace panda::test diff --git a/ecmascript/tests/js_api_list_test.cpp b/ecmascript/tests/js_api_list_test.cpp index b7866c8051..16e4066d7e 100644 --- a/ecmascript/tests/js_api_list_test.cpp +++ b/ecmascript/tests/js_api_list_test.cpp @@ -411,7 +411,8 @@ HWTEST_F_L0(JSAPIListTest, OwnKeys) EXPECT_TRUE(keyArray->GetClass()->IsTaggedArray()); EXPECT_TRUE(keyArray->GetLength() == elementsNums); for (uint32_t i = 0; i < elementsNums; i++) { - EXPECT_EQ(keyArray->Get(i), JSTaggedValue(i)); + ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))), + EcmaString::Cast(keyArray->Get(i).GetTaggedObject()))); } } } // namespace panda::test diff --git a/ecmascript/tests/js_api_queue_test.cpp b/ecmascript/tests/js_api_queue_test.cpp index b2a4cbef59..4970aa15c3 100644 --- a/ecmascript/tests/js_api_queue_test.cpp +++ b/ecmascript/tests/js_api_queue_test.cpp @@ -164,7 +164,8 @@ HWTEST_F_L0(JSAPIQueueTest, OwnKeys) JSHandle arrayKey = JSAPIQueue::OwnKeys(thread, jsQueue); EXPECT_EQ(arrayKey->GetLength(), DEFAULT_LENGTH); for (int32_t i = 0; i < static_cast(DEFAULT_LENGTH); i++) { - EXPECT_EQ(arrayKey->Get(i).GetInt(), i); + ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))), + EcmaString::Cast(arrayKey->Get(i).GetTaggedObject()))); } } diff --git a/ecmascript/tests/js_api_stack_test.cpp b/ecmascript/tests/js_api_stack_test.cpp index ce0d51efbb..e70b324875 100644 --- a/ecmascript/tests/js_api_stack_test.cpp +++ b/ecmascript/tests/js_api_stack_test.cpp @@ -329,7 +329,8 @@ HWTEST_F_L0(JSAPIStackTest, OwnKeys) EXPECT_TRUE(keyArray->GetClass()->IsTaggedArray()); EXPECT_TRUE(keyArray->GetLength() == elementsNums); for (uint32_t i = 0; i < elementsNums; i++) { - EXPECT_EQ(keyArray->Get(i), JSTaggedValue(i)); + ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))), + EcmaString::Cast(keyArray->Get(i).GetTaggedObject()))); } } } // namespace panda::test diff --git a/ecmascript/tests/js_api_vector_test.cpp b/ecmascript/tests/js_api_vector_test.cpp index 04bfbfdeef..0ba6285e5b 100644 --- a/ecmascript/tests/js_api_vector_test.cpp +++ b/ecmascript/tests/js_api_vector_test.cpp @@ -484,7 +484,10 @@ HWTEST_F_L0(JSAPIVectorTest, OwnKeys) EXPECT_TRUE(keyArray->GetClass()->IsTaggedArray()); EXPECT_TRUE(keyArray->GetLength() == elementsNums); for (uint32_t i = 0; i < elementsNums; i++) { - EXPECT_EQ(keyArray->Get(i), JSTaggedValue(i)); + ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual( + *(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))), + EcmaString::Cast(keyArray->Get(i).GetTaggedObject()) + )); } } diff --git a/test/moduletest/BUILD.gn b/test/moduletest/BUILD.gn index 18ff8649a9..0e45c9ad5f 100644 --- a/test/moduletest/BUILD.gn +++ b/test/moduletest/BUILD.gn @@ -30,6 +30,7 @@ group("ark_js_moduletest") { "dynamicimport:dynamicimportAction", "dyninstruction:dyninstructionAction", "ecmastringtable:ecmastringtableAction", + "forin:forinAction", "fortest:fortestAction", "generator:generatorAction", "getunmappedargs:getunmappedargsAction", @@ -95,6 +96,7 @@ group("ark_asm_test") { "dynamicimport:dynamicimportAction", "dyninstruction:dyninstructionAsmAction", "ecmastringtable:ecmastringtableAsmAction", + "forin:forinAsmAction", "fortest:fortestAsmAction", "generator:generatorAsmAction", "getunmappedargs:getunmappedargsAsmAction", @@ -153,6 +155,7 @@ group("ark_asm_single_step_test") { "dynamicimport:dynamicimportAction", "dyninstruction:dyninstructionAsmSingleStepAction", "ecmastringtable:ecmastringtableAsmSingleStepAction", + "forin:forinAsmSingleStepAction", "fortest:fortestAsmSingleStepAction", "generator:generatorAsmSingleStepAction", "getunmappedargs:getunmappedargsAsmSingleStepAction", diff --git a/test/moduletest/container/container_arraylist.js b/test/moduletest/container/container_arraylist.js index 07055557bd..f92c3a8e19 100644 --- a/test/moduletest/container/container_arraylist.js +++ b/test/moduletest/container/container_arraylist.js @@ -239,6 +239,17 @@ if (globalThis["ArkPrivate"] != undefined) { print("ArrayList forEach throw error fail"); } } + let test1 = new arrayList(); + for (let k = 0; k < 10; k++) { + test1.add(k); + } + var keyName = ""; + for (const key in test1) { + keyName += key; + } + if (keyName != "0123456789") { + print("ArrayList for in fail") + } if (!flag) { print("Test ArrayList success!!!"); } else { diff --git a/test/moduletest/container/container_deque.js b/test/moduletest/container/container_deque.js index 5312c4286c..0ec6ee3059 100644 --- a/test/moduletest/container/container_deque.js +++ b/test/moduletest/container/container_deque.js @@ -132,6 +132,17 @@ if (globalThis["ArkPrivate"] != undefined) { print("Deque forEach throw error fail"); } } + let test1 = new Deque(); + for (let k = 0; k < 10; k++) { + test1.insertEnd(k); + } + var keyName = ""; + for (const key in test1) { + keyName += key; + } + if (keyName != "0123456789") { + print("Deque for in fail") + } if (!flag) { print("Test Deque success!!!"); } else { diff --git a/test/moduletest/container/container_queue.js b/test/moduletest/container/container_queue.js index 89db4943db..7bfbe3afcd 100644 --- a/test/moduletest/container/container_queue.js +++ b/test/moduletest/container/container_queue.js @@ -114,7 +114,17 @@ if (globalThis["ArkPrivate"] != undefined) { print("Queue forEach throw error fail"); } } - + let test1 = new Queue(); + for (let k = 0; k < 10; k++) { + test1.add(k); + } + var keyName = ""; + for (const key in test1) { + keyName += key; + } + if (keyName != "0123456789") { + print("Queue for in fail") + } map.forEach(elements); if (!flag) { print("Test Queue success!!!"); diff --git a/test/moduletest/container/container_stack.js b/test/moduletest/container/container_stack.js index 085a943105..2601fdc8f0 100644 --- a/test/moduletest/container/container_stack.js +++ b/test/moduletest/container/container_stack.js @@ -113,6 +113,17 @@ if (globalThis["ArkPrivate"] != undefined) { print("Stack forEach throw error fail"); } } + let test1 = new Stack(); + for (let k = 0; k < 10; k++) { + test1.push(k); + } + var keyName = ""; + for (const key in test1) { + keyName += key; + } + if (keyName != "0123456789") { + print("Stack for in fail") + } if (!flag) { print("Test Stack success!!!"); } else { diff --git a/test/moduletest/container/container_vector.js b/test/moduletest/container/container_vector.js index 0baa008027..090a228996 100644 --- a/test/moduletest/container/container_vector.js +++ b/test/moduletest/container/container_vector.js @@ -294,6 +294,17 @@ if (globalThis["ArkPrivate"] != undefined) { } } map.forEach(elements); + let test1 = new FastVector(); + for (let k = 0; k < 10; k++) { + test1.add(k); + } + var keyName = ""; + for (const key in test1) { + keyName += key; + } + if (keyName != "0123456789") { + print("Vector for in fail") + } if (!flag) { print("Test Vector success!!!"); } else { diff --git a/test/moduletest/forin/BUILD.gn b/test/moduletest/forin/BUILD.gn new file mode 100644 index 0000000000..b608480ba6 --- /dev/null +++ b/test/moduletest/forin/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("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_moduletest_action("forin") { + deps = [] +} diff --git a/test/moduletest/forin/expect_output.txt b/test/moduletest/forin/expect_output.txt new file mode 100644 index 0000000000..70787c5100 --- /dev/null +++ b/test/moduletest/forin/expect_output.txt @@ -0,0 +1,28 @@ +# 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. + +1 +wode +1 +3 +wode +1 +wode +_secret +0 +1 +2 +hhh +0 +1 +2 diff --git a/test/moduletest/forin/forin.js b/test/moduletest/forin/forin.js new file mode 100644 index 0000000000..5233f17eb1 --- /dev/null +++ b/test/moduletest/forin/forin.js @@ -0,0 +1,105 @@ +/* + * 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. + */ + +/* + * @tc.name:builtins + * @tc.desc:test builtins + * @tc.type: FUNC + * @tc.require: issueI5NO8G + */ +var arrayLong = {"1" : "fds", "wode" : "fff"}; +Object.defineProperty(arrayLong, "2", { + configurable:true, + enumerable:true, + value:"ggg", + writable:true +}) +for (const key in arrayLong) { + print(key); + delete arrayLong[2]; +} + +Object.defineProperty(arrayLong, "3", { + configurable:true, + enumerable:true, + value:"ggg", + writable:true +}) +for (const key in arrayLong) { + print(key); + Object.defineProperty(arrayLong, "3", { + configurable:true, + enumerable:false, + value:"fff", + writable:true + }) +} + +Object.defineProperty(arrayLong, "4", { + configurable:true, + enumerable:false, + value:"ggg", + writable:true +}) +for (const key in arrayLong) { + print(key); + Object.defineProperty(arrayLong, "4", { + configurable:true, + enumerable:true, + value:"fff", + writable:true + }) + arrayLong.sss = "fds"; +} + +const targetObj = { + _secret: 'easily scared', + eyeCount: 4 +}; + +Object.defineProperty(targetObj, "wode", { + configurable:true, + enumerable:false, + value:"ggg", + writable:true +}) + +const proxy_has = new Proxy(targetObj, { + has: (target, key) => { + print("key==",key) + if (key.includes('_')) { + return false; + } + return key in target; + } +}) + +for (const key in proxy_has) { + print(key); + delete proxy_has.eyeCount; +} + +var view = new Int16Array(3); +view[1] = 23; +view[2] = 45; +view[3] = 67; +view.hhh = "wode"; +for (const key in view) { + print(key); +} +for (const key in view) { + print(key); + delete view.hhh; +} From 243341a336dfc86015a18d1689293f2d626a9f44 Mon Sep 17 00:00:00 2001 From: wuzhefeng Date: Tue, 22 Nov 2022 22:29:06 -0800 Subject: [PATCH 14/14] Refactor the Schedular of Compiler There are redundant vector-copys in the process of scheduling, which can be eliminated to improve the compiling performance. Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I634ZS Signed-off-by: wuzhefeng Change-Id: I3576cd6c2e76dd1a767d21b9f12a9cbcad68b5e9 --- ecmascript/compiler/code_generator.h | 1 + ecmascript/compiler/pass.h | 12 +++-- ecmascript/compiler/scheduler.cpp | 57 +++++++++++---------- ecmascript/compiler/scheduler.h | 24 ++++++--- ecmascript/compiler/stub_compiler.cpp | 10 ++-- ecmascript/compiler/tests/stub_tests.cpp | 63 +++++++++++++++--------- ecmascript/compiler/verifier.cpp | 18 +++---- ecmascript/frames.cpp | 41 +++++++-------- 8 files changed, 132 insertions(+), 94 deletions(-) diff --git a/ecmascript/compiler/code_generator.h b/ecmascript/compiler/code_generator.h index 920dbfded7..2583ebf361 100644 --- a/ecmascript/compiler/code_generator.h +++ b/ecmascript/compiler/code_generator.h @@ -22,6 +22,7 @@ namespace panda::ecmascript::kungfu { using ControlFlowGraph = std::vector>; + class CodeGeneratorImpl { public: CodeGeneratorImpl() = default; diff --git a/ecmascript/compiler/pass.h b/ecmascript/compiler/pass.h index 9d0c110e0e..9d98d91a8c 100644 --- a/ecmascript/compiler/pass.h +++ b/ecmascript/compiler/pass.h @@ -33,6 +33,7 @@ namespace panda::ecmascript::kungfu { class CompilationInfo; + class PassData { public: explicit PassData(BytecodeCircuitBuilder *builder, Circuit *circuit, CompilationInfo *info, CompilerLog *log, @@ -46,14 +47,15 @@ public: } virtual ~PassData() = default; - const ControlFlowGraph &GetScheduleResult() const + + const ControlFlowGraph &GetConstScheduleResult() const { return cfg_; } - void SetScheduleResult(const ControlFlowGraph &result) + ControlFlowGraph &GetCfg() { - cfg_ = result; + return cfg_; } virtual Circuit* GetCircuit() const @@ -254,7 +256,7 @@ public: { TimeScope timescope("SchedulingPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog()); bool enableLog = data->GetLog()->EnableMethodCIRLog(); - data->SetScheduleResult(Scheduler::Run(data->GetCircuit(), data->GetMethodName(), enableLog)); + Scheduler::Run(data->GetCircuit(), data->GetCfg(), data->GetMethodName(), enableLog); return true; } }; @@ -273,7 +275,7 @@ public: bool enableLog = data->GetLog()->EnableMethodCIRLog(); CreateCodeGen(module, enableLog); CodeGenerator codegen(llvmImpl_, data->GetMethodName()); - codegen.Run(data->GetCircuit(), data->GetScheduleResult(), module->GetCompilationConfig(), + codegen.Run(data->GetCircuit(), data->GetConstScheduleResult(), module->GetCompilationConfig(), data->GetMethodLiteral(), data->GetJSPandaFile()); return true; } diff --git a/ecmascript/compiler/scheduler.cpp b/ecmascript/compiler/scheduler.cpp index bf866e4860..45a06070d1 100644 --- a/ecmascript/compiler/scheduler.cpp +++ b/ecmascript/compiler/scheduler.cpp @@ -12,12 +12,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#include "ecmascript/compiler/scheduler.h" #include #include - #include "ecmascript/compiler/gate_accessor.h" #include "ecmascript/compiler/verifier.h" -#include "ecmascript/compiler/scheduler.h" namespace panda::ecmascript::kungfu { void Scheduler::CalculateDominatorTree(const Circuit *circuit, @@ -116,9 +116,8 @@ void Scheduler::CalculateDominatorTree(const Circuit *circuit, } } -std::vector> Scheduler::Run(const Circuit *circuit, - [[maybe_unused]] const std::string& methodName, - [[maybe_unused]] bool enableLog) +void Scheduler::Run(const Circuit *circuit, ControlFlowGraph &result, + [[maybe_unused]] const std::string& methodName, [[maybe_unused]] bool enableLog) { #ifndef NDEBUG if (!Verifier::Run(circuit, methodName, enableLog)) { @@ -130,7 +129,8 @@ std::vector> Scheduler::Run(const Circuit *circuit, std::unordered_map bbGatesAddrToIdx; std::vector immDom; Scheduler::CalculateDominatorTree(circuit, bbGatesList, bbGatesAddrToIdx, immDom); - std::vector> result(bbGatesList.size()); + ASSERT(result.size() == 0); + result.resize(bbGatesList.size()); for (size_t idx = 0; idx < bbGatesList.size(); idx++) { result[idx].push_back(bbGatesList[idx]); } @@ -200,8 +200,8 @@ std::vector> Scheduler::Run(const Circuit *circuit, }; { std::vector order; - auto lowerBound = - Scheduler::CalculateSchedulingLowerBound(circuit, bbGatesAddrToIdx, lowestCommonAncestor, &order).value(); + std::unordered_map lowerBound; + Scheduler::CalculateSchedulingLowerBound(circuit, bbGatesAddrToIdx, lowestCommonAncestor, lowerBound, &order); for (const auto &schedulableGate : order) { result[lowerBound.at(schedulableGate)].push_back(schedulableGate); } @@ -226,17 +226,15 @@ std::vector> Scheduler::Run(const Circuit *circuit, if (enableLog) { Print(&result, circuit); } - return result; } -std::optional> Scheduler::CalculateSchedulingUpperBound( - const Circuit *circuit, - const std::unordered_map &bbGatesAddrToIdx, - const std::function &isAncestor, - const std::vector &schedulableGatesList) +bool Scheduler::CalculateSchedulingUpperBound(const Circuit *circuit, + const std::unordered_map &bbGatesAddrToIdx, + const std::function &isAncestor, + const std::vector &schedulableGatesList, + std::unordered_map &upperBound) { GateAccessor acc(const_cast(circuit)); - std::unordered_map upperBound; struct DFSState { GateRef curGate = Circuit::NullGate(); std::vector predGates; @@ -296,9 +294,7 @@ std::optional> Scheduler::CalculateSchedulin } auto predUpperBound = returnValue.value(); if (!isAncestor(curUpperBound, predUpperBound) && !isAncestor(predUpperBound, curUpperBound)) { - LOG_COMPILER(ERROR) << "[Verifier][Error] Scheduling upper bound of gate (id=" - << GateAccessor(const_cast(circuit)).GetId(curGate) - << ") does not exist"; + PrintUpperBoundError(circuit, curGate, predUpperBound, curUpperBound); returnValue = std::nullopt; break; } @@ -321,18 +317,30 @@ std::optional> Scheduler::CalculateSchedulin } } if (!returnValue.has_value()) { - return std::nullopt; + return false; } } - return upperBound; + return true; } -std::optional> Scheduler::CalculateSchedulingLowerBound(const Circuit *circuit, - const std::unordered_map &bbGatesAddrToIdx, - const std::function &lowestCommonAncestor, std::vector *order) +void Scheduler::PrintUpperBoundError(const Circuit *circuit, GateRef curGate, + GateRef predUpperBound, GateRef curUpperBound) +{ + GateAccessor ac(const_cast(circuit)); + LOG_COMPILER(ERROR) << "[Verifier][Error] Scheduling upper bound of gate (id=" + << ac.GetId(curGate) + << ") does not exist, current-upper-bound = " + << curUpperBound << ", pred-upper-bound = " + << predUpperBound << ", there is no dominator relationship between them."; +} + +void Scheduler::CalculateSchedulingLowerBound(const Circuit *circuit, + const std::unordered_map &bbGatesAddrToIdx, + const std::function &lowestCommonAncestor, + std::unordered_map &lowerBound, + std::vector *order) { GateAccessor acc(const_cast(circuit)); - std::unordered_map lowerBound; std::unordered_map useCount; std::vector bbAndFixedGatesList; for (const auto &item : bbGatesAddrToIdx) { @@ -434,7 +442,6 @@ std::optional> Scheduler::CalculateSchedulin ++idx; } } - return lowerBound; } void Scheduler::Print(const std::vector> *cfg, const Circuit *circuit) diff --git a/ecmascript/compiler/scheduler.h b/ecmascript/compiler/scheduler.h index 4aa68c30aa..0c7d370c77 100644 --- a/ecmascript/compiler/scheduler.h +++ b/ecmascript/compiler/scheduler.h @@ -27,18 +27,26 @@ public: std::unordered_map &bbGatesAddrToIdx, std::vector &immDom); - static ControlFlowGraph Run(const Circuit *circuit, [[maybe_unused]] const std::string& methodName = "", - bool enableLog = false); + static void Run(const Circuit *circuit, ControlFlowGraph &result, + [[maybe_unused]] const std::string& methodName = "", bool enableLog = false); - static std::optional> CalculateSchedulingUpperBound(const Circuit *circuit, - const std::unordered_map &bbGatesAddrToIdx, - const std::function &isAncestor, const std::vector &schedulableGatesList); + static bool CalculateSchedulingUpperBound(const Circuit *circuit, + const std::unordered_map &bbGatesAddrToIdx, + const std::function &isAncestor, + const std::vector &schedulableGatesList, + std::unordered_map &upperBound); - static std::optional> CalculateSchedulingLowerBound(const Circuit *circuit, - const std::unordered_map &bbGatesAddrToIdx, - const std::function &lowestCommonAncestor, std::vector *order = nullptr); + static void CalculateSchedulingLowerBound(const Circuit *circuit, + const std::unordered_map &bbGatesAddrToIdx, + const std::function &lowestCommonAncestor, + std::unordered_map &lowerBound, + std::vector *order = nullptr); static void Print(const ControlFlowGraph *cfg, const Circuit *circuit); + +private: + static void PrintUpperBoundError(const Circuit *circuit, GateRef curGate, + GateRef predUpperBound, GateRef curUpperBound); }; }; // namespace panda::ecmascript::kungfu diff --git a/ecmascript/compiler/stub_compiler.cpp b/ecmascript/compiler/stub_compiler.cpp index 2229066673..27bcdd5a9e 100644 --- a/ecmascript/compiler/stub_compiler.cpp +++ b/ecmascript/compiler/stub_compiler.cpp @@ -86,7 +86,7 @@ public: auto stubModule = data->GetStubModule(); CreateCodeGen(stubModule, enableLog); CodeGenerator codegen(llvmImpl_, "stubs"); - codegen.RunForStub(data->GetCircuit(), data->GetScheduleResult(), index, data->GetCompilationConfig()); + codegen.RunForStub(data->GetCircuit(), data->GetConstScheduleResult(), index, data->GetCompilationConfig()); return true; } private: @@ -105,15 +105,15 @@ void StubCompiler::RunPipeline(LLVMModule *module) const Circuit circuit(cconfig->Is64Bit()); Stub stub(callSigns[i], &circuit); ASSERT(callSigns[i]->HasConstructor()); - StubBuilder* stubBuilder = static_cast( - callSigns[i]->GetConstructor()(reinterpret_cast(stub.GetEnvironment()))); + void* env = reinterpret_cast(stub.GetEnvironment()); + StubBuilder* stubBuilder = static_cast(callSigns[i]->GetConstructor()(env)); stub.SetStubBuilder(stubBuilder); if (log->CertainMethod()) { enableMethodLog = logList->IncludesMethod(stub.GetMethodName()); } - log->SetEnableMethodLog(enableMethodLog); + StubPassData data(&stub, module, log); PassRunner pipeline(&data); pipeline.RunPass(); @@ -147,6 +147,7 @@ bool StubCompiler::BuildStubModuleAndSave() const RunPipeline(&bcStubModule); generator.AddModule(&bcStubModule, &bcStubAssembler); res++; + LOG_COMPILER(INFO) << "compiling common stubs"; LLVMModule comStubModule("com_stub", triple_, enablePGOProfiler_); LLVMAssembler comStubAssembler(comStubModule.GetModule(), LOptions(optLevel_, true, relocMode_)); @@ -154,6 +155,7 @@ bool StubCompiler::BuildStubModuleAndSave() const RunPipeline(&comStubModule); generator.AddModule(&comStubModule, &comStubAssembler); res++; + LOG_COMPILER(INFO) << "compiling builtins stubs"; LLVMModule builtinsStubModule("builtins_stub", triple_, enablePGOProfiler_); LLVMAssembler builtinsStubAssembler(builtinsStubModule.GetModule(), LOptions(optLevel_, true, relocMode_)); diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index ac34d299d8..c4b1fc57af 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -118,7 +118,8 @@ HWTEST_F_L0(StubTest, FastAddTest) stub.SetStubBuilder(&optimizer); stub.GenerateCircuit(stubModule.GetCompilationConfig()); netOfGates.PrintAllGates(); - auto cfg = Scheduler::Run(&netOfGates); + Scheduler::ControlFlowGraph cfg; + Scheduler::Run(&netOfGates, cfg); PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv); @@ -159,7 +160,8 @@ HWTEST_F_L0(StubTest, FastSubTest) stub.SetStubBuilder(&optimizer); stub.GenerateCircuit(stubModule.GetCompilationConfig()); netOfGates.PrintAllGates(); - auto cfg = Scheduler::Run(&netOfGates); + Scheduler::ControlFlowGraph cfg; + Scheduler::Run(&netOfGates, cfg); PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv); @@ -196,7 +198,8 @@ HWTEST_F_L0(StubTest, FastMulTest) stub.SetStubBuilder(&optimizer); stub.GenerateCircuit(stubModule.GetCompilationConfig()); netOfGates.PrintAllGates(); - auto cfg = Scheduler::Run(&netOfGates); + Scheduler::ControlFlowGraph cfg; + Scheduler::Run(&netOfGates, cfg); PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv); @@ -252,7 +255,8 @@ HWTEST_F_L0(StubTest, FastDivTest) stub.SetStubBuilder(&optimizer); stub.GenerateCircuit(stubModule.GetCompilationConfig()); netOfGates.PrintAllGates(); - auto cfg = Scheduler::Run(&netOfGates); + Scheduler::ControlFlowGraph cfg; + Scheduler::Run(&netOfGates, cfg); PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv); @@ -301,7 +305,8 @@ HWTEST_F_L0(StubTest, FastModTest) stub.SetStubBuilder(&optimizer); stub.GenerateCircuit(stubModule.GetCompilationConfig()); netOfGates.PrintAllGates(); - auto cfg = Scheduler::Run(&netOfGates); + Scheduler::ControlFlowGraph cfg; + Scheduler::Run(&netOfGates, cfg); PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv); @@ -369,7 +374,8 @@ HWTEST_F_L0(StubTest, TryLoadICByName) stub.SetStubBuilder(&optimizer); stub.GenerateCircuit(stubModule.GetCompilationConfig()); netOfGates.PrintAllGates(); - auto cfg = Scheduler::Run(&netOfGates); + Scheduler::ControlFlowGraph cfg; + Scheduler::Run(&netOfGates, cfg); PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, findFunction, stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv); @@ -390,7 +396,8 @@ HWTEST_F_L0(StubTest, TryLoadICByValue) stub.SetStubBuilder(&optimizer); stub.GenerateCircuit(stubModule.GetCompilationConfig()); netOfGates.PrintAllGates(); - auto cfg = Scheduler::Run(&netOfGates); + Scheduler::ControlFlowGraph cfg; + Scheduler::Run(&netOfGates, cfg); PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, findFunction, stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv); @@ -411,7 +418,8 @@ HWTEST_F_L0(StubTest, TryStoreICByName) stub.SetStubBuilder(&optimizer); stub.GenerateCircuit(stubModule.GetCompilationConfig()); netOfGates.PrintAllGates(); - auto cfg = Scheduler::Run(&netOfGates); + Scheduler::ControlFlowGraph cfg; + Scheduler::Run(&netOfGates, cfg); PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, findFunction, stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv); @@ -432,7 +440,8 @@ HWTEST_F_L0(StubTest, TryStoreICByValue) stub.SetStubBuilder(&optimizer); stub.GenerateCircuit(stubModule.GetCompilationConfig()); netOfGates.PrintAllGates(); - auto cfg = Scheduler::Run(&netOfGates); + Scheduler::ControlFlowGraph cfg; + Scheduler::Run(&netOfGates, cfg); PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, findFunction, stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv); @@ -899,7 +908,8 @@ HWTEST_F_L0(StubTest, GetPropertyByIndexStub) stub.SetStubBuilder(&optimizer); stub.GenerateCircuit(stubModule.GetCompilationConfig()); netOfGates.PrintAllGates(); - auto cfg = Scheduler::Run(&netOfGates); + Scheduler::ControlFlowGraph cfg; + Scheduler::Run(&netOfGates, cfg); PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv); @@ -935,7 +945,8 @@ HWTEST_F_L0(StubTest, SetPropertyByIndexStub) netOfGates.PrintAllGates(); bool result = Verifier::Run(&netOfGates); ASSERT_TRUE(result); - auto cfg = Scheduler::Run(&netOfGates); + Scheduler::ControlFlowGraph cfg; + Scheduler::Run(&netOfGates, cfg); PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv); @@ -973,7 +984,8 @@ HWTEST_F_L0(StubTest, GetPropertyByNameStub) netOfGates.PrintAllGates(); bool result = Verifier::Run(&netOfGates); ASSERT_TRUE(result); - auto cfg = Scheduler::Run(&netOfGates); + Scheduler::ControlFlowGraph cfg; + Scheduler::Run(&netOfGates, cfg); PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv); @@ -1011,7 +1023,8 @@ HWTEST_F_L0(StubTest, SetPropertyByNameStub) stub.SetStubBuilder(&optimizer); stub.GenerateCircuit(stubModule.GetCompilationConfig()); netOfGates.PrintAllGates(); - auto cfg = Scheduler::Run(&netOfGates); + Scheduler::ControlFlowGraph cfg; + Scheduler::Run(&netOfGates, cfg); PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv); @@ -1048,8 +1061,9 @@ HWTEST_F_L0(StubTest, GetPropertyByValueStub) stub.SetStubBuilder(&optimizer); stub.GenerateCircuit(stubModule.GetCompilationConfig()); netOfGates2.PrintAllGates(); - auto cfg2 = Scheduler::Run(&netOfGates2); - LLVMIRBuilder llvmBuilder2(&cfg2, &netOfGates2, &stubModule, getPropertyByIndexfunction, + Scheduler::ControlFlowGraph cfg; + Scheduler::Run(&netOfGates2, cfg); + LLVMIRBuilder llvmBuilder2(&cfg, &netOfGates2, &stubModule, getPropertyByIndexfunction, stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv); llvmBuilder2.Build(); @@ -1063,7 +1077,8 @@ HWTEST_F_L0(StubTest, GetPropertyByValueStub) stub1.GenerateCircuit(stubModule.GetCompilationConfig()); bool result = Verifier::Run(&netOfGates1); ASSERT_TRUE(result); - auto cfg1 = Scheduler::Run(&netOfGates1); + Scheduler::ControlFlowGraph cfg1; + Scheduler::Run(&netOfGates1, cfg1); LLVMIRBuilder llvmBuilder1(&cfg1, &netOfGates1, &stubModule, getPropertyByNamefunction, stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv); llvmBuilder1.Build(); @@ -1079,10 +1094,11 @@ HWTEST_F_L0(StubTest, GetPropertyByValueStub) netOfGates.PrintAllGates(); result = Verifier::Run(&netOfGates); ASSERT_TRUE(result); - auto cfg = Scheduler::Run(&netOfGates); - PrintCircuitByBasicBlock(cfg, netOfGates); + Scheduler::ControlFlowGraph cfg2; + Scheduler::Run(&netOfGates, cfg2); + PrintCircuitByBasicBlock(cfg2, netOfGates); - LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(), + LLVMIRBuilder llvmBuilder(&cfg2, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv); llvmBuilder.Build(); LLVMAssembler assembler(module); @@ -1151,7 +1167,8 @@ HWTEST_F_L0(StubTest, FastTypeOfTest) netOfGates.PrintAllGates(); bool verRes = Verifier::Run(&netOfGates); ASSERT_TRUE(verRes); - auto cfg = Scheduler::Run(&netOfGates); + Scheduler::ControlFlowGraph cfg; + Scheduler::Run(&netOfGates, cfg); PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv); @@ -1239,7 +1256,8 @@ HWTEST_F_L0(StubTest, FastEqualTest) stub.SetStubBuilder(&optimizer); stub.GenerateCircuit(stubModule.GetCompilationConfig()); netOfGates.PrintAllGates(); - auto cfg = Scheduler::Run(&netOfGates); + Scheduler::ControlFlowGraph cfg; + Scheduler::Run(&netOfGates, cfg); PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv); @@ -1472,7 +1490,8 @@ HWTEST_F_L0(StubTest, RelocateTest) netOfGates.PrintAllGates(); bool verRes = Verifier::Run(&netOfGates); ASSERT_TRUE(verRes); - auto cfg = Scheduler::Run(&netOfGates); + Scheduler::ControlFlowGraph cfg; + Scheduler::Run(&netOfGates, cfg); PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv); diff --git a/ecmascript/compiler/verifier.cpp b/ecmascript/compiler/verifier.cpp index 93f201f278..ecc2d20074 100644 --- a/ecmascript/compiler/verifier.cpp +++ b/ecmascript/compiler/verifier.cpp @@ -383,26 +383,24 @@ bool Verifier::RunPrologGatesCheck(const Circuit *circuit, const std::vector &schedulableGatesList, - const std::unordered_map &bbGatesAddrToIdx, - const std::function &isAncestor, - const std::function &lowestCommonAncestor) +bool Verifier::RunSchedulingBoundsCheck(const Circuit *circuit, + const std::vector &schedulableGatesList, + const std::unordered_map &bbGatesAddrToIdx, + const std::function &isAncestor, + const std::function &lowestCommonAncestor) { // check existence of scheduling upper bound std::unordered_map upperBound; { - auto result = - Scheduler::CalculateSchedulingUpperBound(circuit, bbGatesAddrToIdx, isAncestor, schedulableGatesList); - if (!result.has_value()) { + if (!Scheduler::CalculateSchedulingUpperBound(circuit, bbGatesAddrToIdx, isAncestor, + schedulableGatesList, upperBound)) { return false; } - upperBound = result.value(); } // check existence of scheduling lower bound std::unordered_map lowerBound; { - auto result = Scheduler::CalculateSchedulingLowerBound(circuit, bbGatesAddrToIdx, lowestCommonAncestor); - lowerBound = result.value(); + Scheduler::CalculateSchedulingLowerBound(circuit, bbGatesAddrToIdx, lowestCommonAncestor, lowerBound); } // check consistency of lower bound and upper bound { diff --git a/ecmascript/frames.cpp b/ecmascript/frames.cpp index 1312ea29c4..44cd6ae5d2 100644 --- a/ecmascript/frames.cpp +++ b/ecmascript/frames.cpp @@ -606,78 +606,79 @@ bool ReadUintptrFromAddr(int pid, uintptr_t addr, uintptr_t &value) bool GetTypeOffsetAndPrevOffsetFromFrameType(uintptr_t frameType, uintptr_t &typeOffset, uintptr_t &prevOffset) { - switch (frameType) { - case (uintptr_t)(FrameType::OPTIMIZED_FRAME): + FrameType type = static_cast(frameType); + switch (type) { + case FrameType::OPTIMIZED_FRAME: typeOffset = OptimizedFrame::GetTypeOffset(); prevOffset = OptimizedFrame::GetPrevOffset(); break; - case (uintptr_t)(FrameType::OPTIMIZED_ENTRY_FRAME): + case FrameType::OPTIMIZED_ENTRY_FRAME: typeOffset = OptimizedEntryFrame::GetTypeOffset(); prevOffset = OptimizedEntryFrame::GetLeaveFrameFpOffset(); break; - case (uintptr_t)(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME): + case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME: typeOffset = OptimizedJSFunctionUnfoldArgVFrame::GetTypeOffset(); prevOffset = OptimizedJSFunctionUnfoldArgVFrame::GetPrevOffset(); break; - case (uintptr_t)(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME): - case (uintptr_t)(FrameType::OPTIMIZED_JS_FUNCTION_FRAME): + case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME: + case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: typeOffset = OptimizedJSFunctionFrame::GetTypeOffset(); prevOffset = OptimizedJSFunctionFrame::GetPrevOffset(); break; - case (uintptr_t)(FrameType::LEAVE_FRAME): + case FrameType::LEAVE_FRAME: typeOffset = MEMBER_OFFSET(OptimizedLeaveFrame, type); prevOffset = MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp); break; - case (uintptr_t)(FrameType::LEAVE_FRAME_WITH_ARGV): + case FrameType::LEAVE_FRAME_WITH_ARGV: typeOffset = MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, type); prevOffset = MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp); break; - case (uintptr_t)(FrameType::BUILTIN_CALL_LEAVE_FRAME): + case FrameType::BUILTIN_CALL_LEAVE_FRAME: typeOffset = OptimizedBuiltinLeaveFrame::GetTypeOffset(); prevOffset = OptimizedBuiltinLeaveFrame::GetPrevOffset(); break; - case (uintptr_t)(FrameType::INTERPRETER_FRAME): - case (uintptr_t)(FrameType::INTERPRETER_FAST_NEW_FRAME): + case FrameType::INTERPRETER_FRAME: + case FrameType::INTERPRETER_FAST_NEW_FRAME: typeOffset = MEMBER_OFFSET(InterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, type); prevOffset = MEMBER_OFFSET(InterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, prev); break; - case (uintptr_t)(FrameType::INTERPRETER_BUILTIN_FRAME): + case FrameType::INTERPRETER_BUILTIN_FRAME: typeOffset = MEMBER_OFFSET(InterpretedBuiltinFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, type); prevOffset = MEMBER_OFFSET(InterpretedBuiltinFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, prev); break; - case (uintptr_t)(FrameType::INTERPRETER_CONSTRUCTOR_FRAME): - case (uintptr_t)(FrameType::ASM_INTERPRETER_FRAME): + case FrameType::INTERPRETER_CONSTRUCTOR_FRAME: + case FrameType::ASM_INTERPRETER_FRAME: typeOffset = MEMBER_OFFSET(AsmInterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, type); prevOffset = MEMBER_OFFSET(AsmInterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, prev); break; - case (uintptr_t)(FrameType::BUILTIN_FRAME): - case (uintptr_t)(FrameType::BUILTIN_ENTRY_FRAME): + case FrameType::BUILTIN_FRAME: + case FrameType::BUILTIN_ENTRY_FRAME: typeOffset = MEMBER_OFFSET(BuiltinFrame, type); prevOffset = MEMBER_OFFSET(BuiltinFrame, prevFp); break; - case (uintptr_t)(FrameType::BUILTIN_FRAME_WITH_ARGV): + case FrameType::BUILTIN_FRAME_WITH_ARGV: typeOffset = MEMBER_OFFSET(BuiltinWithArgvFrame, type); prevOffset = MEMBER_OFFSET(BuiltinWithArgvFrame, prevFp); break; - case (uintptr_t)(FrameType::INTERPRETER_ENTRY_FRAME): + case FrameType::INTERPRETER_ENTRY_FRAME: typeOffset = MEMBER_OFFSET(InterpretedEntryFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, type); prevOffset = MEMBER_OFFSET(InterpretedEntryFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, prev); break; - case (uintptr_t)(FrameType::ASM_INTERPRETER_ENTRY_FRAME): + case FrameType::ASM_INTERPRETER_ENTRY_FRAME: typeOffset = MEMBER_OFFSET(AsmInterpretedEntryFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, type); prevOffset = MEMBER_OFFSET(AsmInterpretedEntryFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, prev); break; - case (uintptr_t)(FrameType::ASM_INTERPRETER_BRIDGE_FRAME): + case FrameType::ASM_INTERPRETER_BRIDGE_FRAME: typeOffset = MEMBER_OFFSET(AsmInterpretedBridgeFrame, entry) + MEMBER_OFFSET(AsmInterpretedEntryFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, type);