From 61d7585a4024a07c0640ab98d606b9929b857ac9 Mon Sep 17 00:00:00 2001 From: ywx Date: Tue, 3 Dec 2024 20:26:15 +0800 Subject: [PATCH] Optimize Is In. Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IB8U8B?from=project-issue Signed-off-by: yinwuxiao Change-Id: Iaf9b96be4dae879a20d22b3f58500fe38e2430a4 --- ecmascript/compiler/stub_builder.cpp | 4 +- ecmascript/ecma_string.h | 10 ++++ ecmascript/js_tagged_value.cpp | 5 +- ecmascript/object_operator.cpp | 27 ++++++++++- ecmascript/object_operator.h | 1 + test/moduletest/BUILD.gn | 3 ++ test/moduletest/internstring/BUILD.gn | 18 ++++++++ .../moduletest/internstring/expect_output.txt | 41 +++++++++++++++++ test/moduletest/internstring/internstring.js | 46 +++++++++++++++++++ 9 files changed, 152 insertions(+), 3 deletions(-) create mode 100644 test/moduletest/internstring/BUILD.gn create mode 100644 test/moduletest/internstring/expect_output.txt create mode 100644 test/moduletest/internstring/internstring.js diff --git a/ecmascript/compiler/stub_builder.cpp b/ecmascript/compiler/stub_builder.cpp index e9653cac38..524ee697ed 100644 --- a/ecmascript/compiler/stub_builder.cpp +++ b/ecmascript/compiler/stub_builder.cpp @@ -8065,7 +8065,7 @@ GateRef StubBuilder::ToPrototypeOrObj(GateRef glue, GateRef obj) env->SubCfgEntry(&entry); Label exit(env); DEFVARIABLE(result, VariableType::JS_ANY(), obj); - + Label isNotEcmaObject(env); Label isNumber(env); Label notNumber(env); Label isBoolean(env); @@ -8075,6 +8075,8 @@ GateRef StubBuilder::ToPrototypeOrObj(GateRef glue, GateRef obj) Label isSymbol(env); Label notSymbol(env); Label isBigInt(env); + BRANCH(IsEcmaObject(obj), &exit, &isNotEcmaObject); + Bind(&isNotEcmaObject); BRANCH(TaggedIsNumber(obj), &isNumber, ¬Number); Bind(&isNumber); { diff --git a/ecmascript/ecma_string.h b/ecmascript/ecma_string.h index 4fd8bf4c09..a7cf3b0a7f 100755 --- a/ecmascript/ecma_string.h +++ b/ecmascript/ecma_string.h @@ -1538,6 +1538,16 @@ public: return string_->IsLineOrConstantString(); } + bool IsInteger() const + { + return string_->IsInteger(); + } + + uint32_t GetIntegerCode() const + { + return string_->GetIntegerCode(); + } + JSType GetStringType() const { return string_->GetStringType(); diff --git a/ecmascript/js_tagged_value.cpp b/ecmascript/js_tagged_value.cpp index 14ac8d7c2d..cf50665795 100644 --- a/ecmascript/js_tagged_value.cpp +++ b/ecmascript/js_tagged_value.cpp @@ -1460,8 +1460,11 @@ bool JSTaggedValue::ToArrayLength(JSThread *thread, const JSHandle JSTaggedValue::ToPrototypeOrObj(JSThread *thread, const JSHandle &obj) { + if (obj->IsECMAObject()) { + return obj; + } + JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); - if (obj->IsNumber()) { return JSHandle(thread, env->GetNumberFunction().GetObject()->GetFunctionPrototype()); diff --git a/ecmascript/object_operator.cpp b/ecmascript/object_operator.cpp index 8de99552ad..ba49128f09 100644 --- a/ecmascript/object_operator.cpp +++ b/ecmascript/object_operator.cpp @@ -21,6 +21,25 @@ #include "ecmascript/property_detector-inl.h" namespace panda::ecmascript { +bool ObjectOperator::TryFastHandleStringKey(const JSHandle &key) +{ + if (!EcmaStringAccessor(key->GetTaggedObject()).IsInternString()) { + return false; + } + if (EcmaStringAccessor(key->GetTaggedObject()).IsInteger()) { + elementIndex_ = EcmaStringAccessor(key->GetTaggedObject()).GetIntegerCode(); + return true; + } + if (EcmaStringAccessor(key->GetTaggedObject()).GetLength() <= EcmaString::MAX_CACHED_INTEGER_SIZE) { + // Since the range of hash values is of the int32 type, + // the IsInteger() function can only accurately determine + // a string whose length is less than or equal to MAX_CACHED_INTEGER_SIZE is not a number. + key_ = key; + return true; + } + return false; +} + void ObjectOperator::HandleKey(const JSHandle &key) { if (key->IsInt()) { @@ -35,8 +54,11 @@ void ObjectOperator::HandleKey(const JSHandle &key) if (key->IsString()) { keyFromStringType_ = true; + if (TryFastHandleStringKey(key)) { + return; + } uint32_t index = 0; - if (JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index)) { + if (JSTaggedValue::StringToElementIndex(key.GetTaggedValue(), &index)) { ASSERT(index < JSObject::MAX_ELEMENT_INDEX); elementIndex_ = index; return; @@ -83,6 +105,9 @@ void ObjectOperator::HandleKey(const JSHandle &key) void ObjectOperator::UpdateHolder() { + if (holder_->IsECMAObject()) { + return; + } if (holder_->IsString() && (GetThroughElement() || GetStringLength())) { JSHandle undefined = thread_->GlobalConstants()->GetHandledUndefined(); holder_.Update(JSPrimitiveRef::StringCreate(thread_, holder_, undefined).GetTaggedValue()); diff --git a/ecmascript/object_operator.h b/ecmascript/object_operator.h index baf73ee0e9..39b1814d2f 100644 --- a/ecmascript/object_operator.h +++ b/ecmascript/object_operator.h @@ -332,6 +332,7 @@ private: void UpdateHolder(); void StartLookUp(OperatorType type); void StartGlobalLookUp(OperatorType type); + bool TryFastHandleStringKey(const JSHandle &key); void HandleKey(const JSHandle &key); uint32_t ComputeElementCapacity(uint32_t oldCapacity); void SetFound(uint32_t index, JSTaggedValue value, uint64_t attr, bool mode, bool transition = false); diff --git a/test/moduletest/BUILD.gn b/test/moduletest/BUILD.gn index d8165ccba3..e5f5537c1a 100644 --- a/test/moduletest/BUILD.gn +++ b/test/moduletest/BUILD.gn @@ -70,6 +70,7 @@ group("ark_js_moduletest") { "dynamicimport", "dyninstruction", "ecmastringtable", + "internstring", "equal", "errorhelper", "errorcause", @@ -313,6 +314,7 @@ group("ark_asm_test") { "dynamicimport", "dyninstruction", "ecmastringtable", + "internstring", "elements_kind", "equal", "errorcause", @@ -511,6 +513,7 @@ group("ark_asm_single_step_test") { "dynamicimport", "dyninstruction", "ecmastringtable", + "internstring", "errorcause", "exp", "forin", diff --git a/test/moduletest/internstring/BUILD.gn b/test/moduletest/internstring/BUILD.gn new file mode 100644 index 0000000000..ed03a9d94b --- /dev/null +++ b/test/moduletest/internstring/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright (c) 2024 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("internstring") { + deps = [] +} diff --git a/test/moduletest/internstring/expect_output.txt b/test/moduletest/internstring/expect_output.txt new file mode 100644 index 0000000000..6d48d761f0 --- /dev/null +++ b/test/moduletest/internstring/expect_output.txt @@ -0,0 +1,41 @@ +# Copyright (c) 2024 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. + +id: 12345678 - load: undefined +id: 1234567891 - load: undefined +id: 9999999999 - load: undefined +id: 135 - load: undefined +id: 0 - load: undefined +id: abc - load: undefined +id: cba - load: undefined +id: 12345678 - load: 12345678 +id: 1234567891 - load: 1234567891 +id: 9999999999 - load: 9999999999 +id: 135 - load: 135 +id: 0 - load: 0 +id: abc - load: abc +id: cba - load: cba +id: 12345678 - load: undefined +id: 1234567891 - load: undefined +id: 9999999999 - load: undefined +id: 135 - load: undefined +id: 0 - load: undefined +id: abc - load: undefined +id: cba - load: undefined +id: 12345678 - load: 12345678 +id: 1234567891 - load: 1234567891 +id: 9999999999 - load: 9999999999 +id: 135 - load: 135 +id: 0 - load: 0 +id: abc - load: abc +id: cba - load: cba \ No newline at end of file diff --git a/test/moduletest/internstring/internstring.js b/test/moduletest/internstring/internstring.js new file mode 100644 index 0000000000..884d3d4f97 --- /dev/null +++ b/test/moduletest/internstring/internstring.js @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024 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: internstring + * @tc.desc: Test internstring fast check is number or not + * @tc.type: FUNC + */ +{ + let REGISTRY = Symbol(); + function System() { + this[REGISTRY] = {}; + } + + function SetAndPrintLoad(loader, id) { + let load = loader[REGISTRY][id]; + print("id: " + id + " - load: "+ load); + if (loader[REGISTRY][id] == undefined) { + loader[REGISTRY][id] = id; + } else { + loader[REGISTRY][id] = undefined; + } + } + + let keyArray = ["12345678", "1234567891", "9999999999", "135", "0", "abc", "cba", + "12345678", "1234567891", "9999999999", "135", "0", "abc", "cba"]; + + let system = new System(); + for (let T = 0; T < 2; T++) { + for (let i = 0; i < keyArray.length; i++) { + SetAndPrintLoad(system, keyArray[i]); + } + } +} \ No newline at end of file -- Gitee