From a71bceff372deebd61e0372f1bc3c64ab0596d83 Mon Sep 17 00:00:00 2001 From: lichenshuai Date: Tue, 25 Oct 2022 19:50:12 +0800 Subject: [PATCH] LightWeightMap LightWeightSet ForEach IR Use IR to save time and to avoid JSFunction::Call(). Isuue: #I5XO4T Signed-off-by: lichenshuai Change-Id: I834bf28f9cc66c3e4c8d92ff18b5f2d8e9a41b90 --- .../builtins/builtins_call_signature.h | 2 + .../compiler/builtins/builtins_stubs.cpp | 42 +++++++ .../containers_lightweightmap_stub_builder.h | 51 +++++++++ .../containers_lightweightset_stub_builder.h | 49 +++++++++ .../builtins/containers_stub_builder.cpp | 104 ++++++++++++++++++ .../builtins/containers_stub_builder.h | 45 ++++++++ ecmascript/compiler/stub_builder-inl.h | 12 ++ ecmascript/compiler/stub_builder.h | 2 + .../containers/containers_lightweightmap.cpp | 10 +- ecmascript/containers/containers_private.cpp | 6 +- ecmascript/js_api/js_api_lightweightset.cpp | 6 +- 11 files changed, 319 insertions(+), 10 deletions(-) create mode 100644 ecmascript/compiler/builtins/containers_lightweightmap_stub_builder.h create mode 100644 ecmascript/compiler/builtins/containers_lightweightset_stub_builder.h diff --git a/ecmascript/compiler/builtins/builtins_call_signature.h b/ecmascript/compiler/builtins/builtins_call_signature.h index f7247d866c..05434fbac3 100644 --- a/ecmascript/compiler/builtins/builtins_call_signature.h +++ b/ecmascript/compiler/builtins/builtins_call_signature.h @@ -31,6 +31,8 @@ namespace panda::ecmascript::kungfu { V(PlainArrayForEach) \ V(QueueForEach) \ V(DequeForEach) \ + V(LightWeightMapForEach) \ + V(LightWeightSetForEach) \ class BuiltinsStubCSigns { public: diff --git a/ecmascript/compiler/builtins/builtins_stubs.cpp b/ecmascript/compiler/builtins/builtins_stubs.cpp index 63d684e05f..2bc03c0aca 100644 --- a/ecmascript/compiler/builtins/builtins_stubs.cpp +++ b/ecmascript/compiler/builtins/builtins_stubs.cpp @@ -600,4 +600,46 @@ DECLARE_BUILTINS(DequeForEach) Bind(&exit); Return(*res); } + +DECLARE_BUILTINS(LightWeightMapForEach) +{ + auto env = GetEnvironment(); + DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined()); + + Label exit(env); + Label slowPath(env); + + ContainersStubBuilder containersBuilder(this); + containersBuilder.ContainersLightWeightCall(glue, thisValue, numArgs, &res, &exit, + &slowPath, ContainersType::LIGHTWEIGHTMAP_FOREACH); + Bind(&slowPath); + { + BUILDARG(); + res = CALLSLOWPATH(); + Jump(&exit); + } + Bind(&exit); + Return(*res); +} + +DECLARE_BUILTINS(LightWeightSetForEach) +{ + auto env = GetEnvironment(); + DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined()); + + Label exit(env); + Label slowPath(env); + + ContainersStubBuilder containersBuilder(this); + containersBuilder.ContainersLightWeightCall(glue, thisValue, numArgs, &res, &exit, + &slowPath, ContainersType::LIGHTWEIGHTSET_FOREACH); + Bind(&slowPath); + { + BUILDARG(); + res = CALLSLOWPATH(); + Jump(&exit); + } + Bind(&exit); + Return(*res); +} } // namespace panda::ecmascript::kungfu \ No newline at end of file diff --git a/ecmascript/compiler/builtins/containers_lightweightmap_stub_builder.h b/ecmascript/compiler/builtins/containers_lightweightmap_stub_builder.h new file mode 100644 index 0000000000..16328c3164 --- /dev/null +++ b/ecmascript/compiler/builtins/containers_lightweightmap_stub_builder.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_LIGHTWEIGHTMAP_STUB_BUILDER_H +#define ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_LIGHTWEIGHTMAP_STUB_BUILDER_H +#include "ecmascript/compiler/stub_builder-inl.h" +#include "ecmascript/js_api/js_api_lightweightmap.h" + +namespace panda::ecmascript::kungfu { +class ContainersLightWeightMapStubBuilder : public StubBuilder { +public: + explicit ContainersLightWeightMapStubBuilder(StubBuilder *parent) + : StubBuilder(parent) {} + ~ContainersLightWeightMapStubBuilder() = default; + NO_MOVE_SEMANTIC(ContainersLightWeightMapStubBuilder); + NO_COPY_SEMANTIC(ContainersLightWeightMapStubBuilder); + void GenerateCircuit() override {} + + GateRef GetSize(GateRef obj) + { + return Load(VariableType::INT32(), obj, IntPtr(JSAPILightWeightMap::LWP_LENGTH_OFFSET)); + } + + GateRef GetKey(GateRef obj, GateRef index) + { + GateRef keysOffset = IntPtr(JSAPILightWeightMap::LWP_KEYS_OFFSET); + GateRef keys = Load(VariableType::JS_POINTER(), obj, keysOffset); + return GetValueFromTaggedArray(keys, index); + } + + GateRef GetValue(GateRef obj, GateRef index) + { + GateRef valuesOffset = IntPtr(JSAPILightWeightMap::LWP_VALUES_OFFSET); + GateRef values = Load(VariableType::JS_POINTER(), obj, valuesOffset); + return GetValueFromTaggedArray(values, index); + } +}; +} // namespace panda::ecmascript::kungfu +#endif // ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_VECTOR_STUB_BUILDER_H \ No newline at end of file diff --git a/ecmascript/compiler/builtins/containers_lightweightset_stub_builder.h b/ecmascript/compiler/builtins/containers_lightweightset_stub_builder.h new file mode 100644 index 0000000000..eb6f6dcc4b --- /dev/null +++ b/ecmascript/compiler/builtins/containers_lightweightset_stub_builder.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_LIGHTWEIGHTSET_STUB_BUILDER_H +#define ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_LIGHTWEIGHTSET_STUB_BUILDER_H +#include "ecmascript/compiler/stub_builder-inl.h" +#include "ecmascript/js_api/js_api_lightweightset.h" + +namespace panda::ecmascript::kungfu { +class ContainersLightWeightSetStubBuilder : public StubBuilder { +public: + explicit ContainersLightWeightSetStubBuilder(StubBuilder *parent) + : StubBuilder(parent) {} + ~ContainersLightWeightSetStubBuilder() = default; + NO_MOVE_SEMANTIC(ContainersLightWeightSetStubBuilder); + NO_COPY_SEMANTIC(ContainersLightWeightSetStubBuilder); + void GenerateCircuit() override {} + + GateRef GetSize(GateRef obj) + { + return Load(VariableType::INT32(), obj, IntPtr(JSAPILightWeightSet::LENGTH_OFFSET)); + } + + GateRef GetKey(GateRef obj, GateRef index) + { + return GetValue(obj, index); + } + + GateRef GetValue(GateRef obj, GateRef index) + { + GateRef valuesOffset = IntPtr(JSAPILightWeightSet::VALUES_OFFSET); + GateRef values = Load(VariableType::JS_POINTER(), obj, valuesOffset); + return GetValueFromTaggedArray(values, index); + } +}; +} // namespace panda::ecmascript::kungfu +#endif // ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_VECTOR_STUB_BUILDER_H \ No newline at end of file diff --git a/ecmascript/compiler/builtins/containers_stub_builder.cpp b/ecmascript/compiler/builtins/containers_stub_builder.cpp index cab2199b8e..3df4ee4a12 100644 --- a/ecmascript/compiler/builtins/containers_stub_builder.cpp +++ b/ecmascript/compiler/builtins/containers_stub_builder.cpp @@ -340,4 +340,108 @@ void ContainersStubBuilder::DequeCommonFuncCall(GateRef glue, GateRef thisValue, Bind(&afterLoop); Jump(exit); } + +void ContainersStubBuilder::ContainersLightWeightCall(GateRef glue, GateRef thisValue, + GateRef numArgs, Variable* result, Label *exit, Label *slowPath, ContainersType type) +{ + auto env = GetEnvironment(); + DEFVARIABLE(thisObj, VariableType::JS_ANY(), thisValue); + DEFVARIABLE(thisArg, VariableType::JS_ANY(), Undefined()); + DEFVARIABLE(key, VariableType::JS_ANY(), Undefined()); + DEFVARIABLE(value, VariableType::JS_ANY(), Undefined()); + DEFVARIABLE(length, VariableType::INT32(), Int32(0)); + DEFVARIABLE(index, VariableType::INT32(), Int32(0)); + Label valueIsJSAPILightWeight(env); + Label valueNotJSAPILightWeight(env); + Label objIsJSProxy(env); + Label objNotJSProxy(env); + Label objIsJSAPILightWeight(env); + Label thisArgUndefined(env); + Label thisArgNotUndefined(env); + Label callbackUndefined(env); + Label callbackNotUndefined(env); + Label nextCount(env); + Label loopHead(env); + Label loopEnd(env); + Label next(env); + Label afterLoop(env); + GateRef callbackFnHandle; + Branch(IsContainer(*thisObj, type), &valueIsJSAPILightWeight, &valueNotJSAPILightWeight); + Bind(&valueNotJSAPILightWeight); + { + Branch(IsJsProxy(*thisObj), &objIsJSProxy, &objNotJSProxy); + Bind(&objIsJSProxy); + { + GateRef tempObj = GetTarget(*thisObj); + Branch(IsContainer(tempObj, type), &objIsJSAPILightWeight, slowPath); + Bind(&objIsJSAPILightWeight); + { + thisObj = tempObj; + Jump(&valueIsJSAPILightWeight); + } + } + Bind(&objNotJSProxy); + Jump(slowPath); + } + Bind(&valueIsJSAPILightWeight); + { + Branch(Int64GreaterThanOrEqual(IntPtr(0), numArgs), &callbackUndefined, &callbackNotUndefined); + Bind(&callbackUndefined); + Jump(slowPath); + Bind(&callbackNotUndefined); + { + Label isCall(env); + Label notCall(env); + callbackFnHandle = GetCallArg0(); + Branch(IsCallable(callbackFnHandle), &isCall, ¬Call); + Bind(¬Call); + Jump(slowPath); + Bind(&isCall); + { + Branch(Int64GreaterThanOrEqual(IntPtr(1), numArgs), &thisArgUndefined, &thisArgNotUndefined); + Bind(&thisArgUndefined); + Jump(&nextCount); + Bind(&thisArgNotUndefined); + thisArg = GetCallArg1(); + Jump(&nextCount); + } + } + } + Bind(&nextCount); + { + length = ContainerGetSize(*thisObj, type); + Jump(&loopHead); + LoopBegin(&loopHead); + { + Label lenChange(env); + Label hasException(env); + Label notHasException(env); + Branch(Int32LessThan(*index, *length), &next, &afterLoop); + Bind(&next); + { + value = ContainerGetValue(*thisObj, *index, type); + key = ContainerGetKey(*thisObj, *index, type); + GateRef retValue = JSCallDispatch(glue, callbackFnHandle, Int32(3), 0, // 3: numArgs + JSCallMode::CALL_THIS_ARG3_WITH_RETURN, { *thisArg, *value, *key, *thisObj }); + Branch(HasPendingException(glue), &hasException, ¬HasException); + Bind(&hasException); + { + result->WriteVariable(retValue); + Jump(exit); + } + Bind(¬HasException); + GateRef currentLen = ContainerGetSize(*thisObj, type); + Branch(Int32NotEqual(currentLen, *length), &lenChange, &loopEnd); + Bind(&lenChange); + length = currentLen; + Jump(&loopEnd); + } + } + Bind(&loopEnd); + index = Int32Add(*index, Int32(1)); + LoopEnd(&loopHead); + } + Bind(&afterLoop); + Jump(exit); +} } // namespace panda::ecmascript::kungfu diff --git a/ecmascript/compiler/builtins/containers_stub_builder.h b/ecmascript/compiler/builtins/containers_stub_builder.h index f66dc9ca89..3c4da0b2de 100644 --- a/ecmascript/compiler/builtins/containers_stub_builder.h +++ b/ecmascript/compiler/builtins/containers_stub_builder.h @@ -16,6 +16,8 @@ #ifndef ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_STUB_BUILDER_H #define ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_STUB_BUILDER_H #include "ecmascript/compiler/builtins/containers_deque_stub_builder.h" +#include "ecmascript/compiler/builtins/containers_lightweightmap_stub_builder.h" +#include "ecmascript/compiler/builtins/containers_lightweightset_stub_builder.h" #include "ecmascript/compiler/builtins/containers_plainarray_stub_builder.h" #include "ecmascript/compiler/builtins/containers_queue_stub_builder.h" #include "ecmascript/compiler/builtins/containers_stack_stub_builder.h" @@ -32,6 +34,8 @@ enum class ContainersType : uint8_t { PLAINARRAY_FOREACH, QUEUE_FOREACH, DEQUE_FOREACH, + LIGHTWEIGHTMAP_FOREACH, + LIGHTWEIGHTSET_FOREACH, }; class ContainersStubBuilder : public BuiltinsStubBuilder { @@ -52,6 +56,9 @@ public: void DequeCommonFuncCall(GateRef glue, GateRef thisValue, GateRef numArgs, Variable* result, Label *exit, Label *slowPath, ContainersType type); + void ContainersLightWeightCall(GateRef glue, GateRef thisValue, GateRef numArgs, + Variable* result, Label *exit, Label *slowPath, ContainersType type); + GateRef IsContainer(GateRef obj, ContainersType type) { switch (type) { @@ -66,6 +73,10 @@ public: return IsJSAPIQueue(obj); case ContainersType::DEQUE_FOREACH: return IsJSAPIDeque(obj); + case ContainersType::LIGHTWEIGHTMAP_FOREACH: + return IsJSAPILightWeightMap(obj); + case ContainersType::LIGHTWEIGHTSET_FOREACH: + return IsJSAPILightWeightSet(obj); default: UNREACHABLE(); } @@ -142,6 +153,14 @@ public: ContainersDequeStubBuilder dequeBuilder(this); return dequeBuilder.GetSize(obj); } + case ContainersType::LIGHTWEIGHTMAP_FOREACH: { + ContainersLightWeightMapStubBuilder lightWeightMapBuilder(this); + return lightWeightMapBuilder.GetSize(obj); + } + case ContainersType::LIGHTWEIGHTSET_FOREACH: { + ContainersLightWeightSetStubBuilder lightWeightSetBuilder(this); + return lightWeightSetBuilder.GetSize(obj); + } default: UNREACHABLE(); } @@ -172,11 +191,37 @@ public: ContainersDequeStubBuilder dequeBuilder(this); return dequeBuilder.Get(obj, index); } + case ContainersType::LIGHTWEIGHTMAP_FOREACH: { + ContainersLightWeightMapStubBuilder lightWeightMapBuilder(this); + return lightWeightMapBuilder.GetValue(obj, index); + } + case ContainersType::LIGHTWEIGHTSET_FOREACH: { + ContainersLightWeightSetStubBuilder lightWeightSetBuilder(this); + return lightWeightSetBuilder.GetValue(obj, index); + } default: UNREACHABLE(); } return False(); } + + GateRef ContainerGetKey(GateRef obj, GateRef index, ContainersType type) + { + switch (type) { + case ContainersType::LIGHTWEIGHTMAP_FOREACH: { + ContainersLightWeightMapStubBuilder lightWeightMapBuilder(this); + return lightWeightMapBuilder.GetKey(obj, index); + } + case ContainersType::LIGHTWEIGHTSET_FOREACH: { + ContainersLightWeightSetStubBuilder lightWeightSetBuilder(this); + return lightWeightSetBuilder.GetKey(obj, index); + } + default: + UNREACHABLE(); + } + return False(); + } + GateRef PlainArrayGetKey(GateRef obj, GateRef index) { ContainersPlainArrayStubBuilder plainArrayBuilder(this); diff --git a/ecmascript/compiler/stub_builder-inl.h b/ecmascript/compiler/stub_builder-inl.h index 5b1fe339b1..e475d503ca 100644 --- a/ecmascript/compiler/stub_builder-inl.h +++ b/ecmascript/compiler/stub_builder-inl.h @@ -1085,6 +1085,18 @@ inline GateRef StubBuilder::IsJSAPIDeque(GateRef obj) return Int32Equal(objectType, Int32(static_cast(JSType::JS_API_DEQUE))); } +inline GateRef StubBuilder::IsJSAPILightWeightMap(GateRef obj) +{ + GateRef objectType = GetObjectType(LoadHClass(obj)); + return Int32Equal(objectType, Int32(static_cast(JSType::JS_API_LIGHT_WEIGHT_MAP))); +} + +inline GateRef StubBuilder::IsJSAPILightWeightSet(GateRef obj) +{ + GateRef objectType = GetObjectType(LoadHClass(obj)); + return Int32Equal(objectType, Int32(static_cast(JSType::JS_API_LIGHT_WEIGHT_SET))); +} + inline GateRef StubBuilder::GetTarget(GateRef proxyObj) { GateRef offset = IntPtr(JSProxy::TARGET_OFFSET); diff --git a/ecmascript/compiler/stub_builder.h b/ecmascript/compiler/stub_builder.h index a13eb99b0b..b6c92c70bc 100644 --- a/ecmascript/compiler/stub_builder.h +++ b/ecmascript/compiler/stub_builder.h @@ -260,6 +260,8 @@ public: GateRef IsJSAPIPlainArray(GateRef obj); GateRef IsJSAPIQueue(GateRef obj); GateRef IsJSAPIDeque(GateRef obj); + GateRef IsJSAPILightWeightMap(GateRef attr); + GateRef IsJSAPILightWeightSet(GateRef attr); GateRef GetTarget(GateRef proxyObj); GateRef HandlerBaseIsAccessor(GateRef attr); GateRef HandlerBaseIsJSArray(GateRef attr); diff --git a/ecmascript/containers/containers_lightweightmap.cpp b/ecmascript/containers/containers_lightweightmap.cpp index 802730f829..02055edbc7 100644 --- a/ecmascript/containers/containers_lightweightmap.cpp +++ b/ecmascript/containers/containers_lightweightmap.cpp @@ -540,13 +540,12 @@ JSTaggedValue ContainersLightWeightMap::ForEach(EcmaRuntimeCallInfo *argv) JSHandle tmap = JSHandle::Cast(self); JSMutableHandle keys(thread, tmap->GetKeys()); JSMutableHandle values(thread, tmap->GetValues()); - int elements = tmap->GetSize(); int index = 0; - uint32_t length = keys->GetLength(); + int32_t length = tmap->GetSize(); const int32_t argsLength = 3; JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); - while (index < elements) { + while (index < length) { // ignore the hash value is required to determine the true index // Let funcResult be Call(callbackfn, T, «e, e, S»). EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, func, thisArg, undefined, argsLength); @@ -556,11 +555,10 @@ JSTaggedValue ContainersLightWeightMap::ForEach(EcmaRuntimeCallInfo *argv) RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ret); // check entries should be update, size will be update in tmap set or remove. - if (tmap->GetLength() != length) { + if (tmap->GetSize() != length) { keys.Update(tmap->GetKeys()); values.Update(tmap->GetValues()); - elements = tmap->GetSize(); - length = keys->GetLength(); + length = tmap->GetSize(); } index++; } diff --git a/ecmascript/containers/containers_private.cpp b/ecmascript/containers/containers_private.cpp index 4afb1291a8..4e462fdc7c 100644 --- a/ecmascript/containers/containers_private.cpp +++ b/ecmascript/containers/containers_private.cpp @@ -381,7 +381,8 @@ JSHandle ContainersPrivate::InitializeLightWeightMap(JSThread *th SetFrozenFunction(thread, funcPrototype, "removeAt", ContainersLightWeightMap::RemoveAt, FuncLength::ONE); SetFrozenFunction(thread, funcPrototype, "clear", ContainersLightWeightMap::Clear, FuncLength::ONE); SetFrozenFunction(thread, funcPrototype, "setValueAt", ContainersLightWeightMap::SetValueAt, FuncLength::ONE); - SetFrozenFunction(thread, funcPrototype, "forEach", ContainersLightWeightMap::ForEach, FuncLength::ONE); + SetFrozenFunction(thread, funcPrototype, "forEach", ContainersLightWeightMap::ForEach, FuncLength::ONE, + static_cast(BUILTINS_STUB_ID(LightWeightMapForEach))); SetFrozenFunction(thread, funcPrototype, "toString", ContainersLightWeightMap::ToString, FuncLength::ONE); SetFrozenFunction(thread, funcPrototype, "getValueAt", ContainersLightWeightMap::GetValueAt, FuncLength::ONE); SetFrozenFunction(thread, funcPrototype, "values", ContainersLightWeightMap::Values, FuncLength::ONE); @@ -441,7 +442,8 @@ JSHandle ContainersPrivate::InitializeLightWeightSet(JSThread *th SetFrozenFunction(thread, funcPrototype, "equal", ContainersLightWeightSet::Equal, FuncLength::ONE); SetFrozenFunction(thread, funcPrototype, "increaseCapacityTo", ContainersLightWeightSet::IncreaseCapacityTo, FuncLength::ONE); - SetFrozenFunction(thread, funcPrototype, "forEach", ContainersLightWeightSet::ForEach, FuncLength::ONE); + SetFrozenFunction(thread, funcPrototype, "forEach", ContainersLightWeightSet::ForEach, FuncLength::ONE, + static_cast(BUILTINS_STUB_ID(LightWeightSetForEach))); SetFrozenFunction(thread, funcPrototype, "getIndexOf", ContainersLightWeightSet::GetIndexOf, FuncLength::ONE); SetFrozenFunction(thread, funcPrototype, "remove", ContainersLightWeightSet::Remove, FuncLength::ZERO); SetFrozenFunction(thread, funcPrototype, "removeAt", ContainersLightWeightSet::RemoveAt, FuncLength::ZERO); diff --git a/ecmascript/js_api/js_api_lightweightset.cpp b/ecmascript/js_api/js_api_lightweightset.cpp index a49c4f9ca9..75f394e106 100644 --- a/ecmascript/js_api/js_api_lightweightset.cpp +++ b/ecmascript/js_api/js_api_lightweightset.cpp @@ -329,13 +329,15 @@ JSTaggedValue JSAPILightWeightSet::ForEach(JSThread *thread, const JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); for (uint32_t k = 0; k < length; k++) { JSTaggedValue kValue = lightweightset->GetValueAt(k); - JSTaggedValue kHash = lightweightset->GetHashAt(k); EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFn, thisArg, undefined, 3); // 3:three args RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception()); - info->SetCallArg(kValue, kHash, thisHandle.GetTaggedValue()); + info->SetCallArg(kValue, kValue, thisHandle.GetTaggedValue()); JSTaggedValue funcResult = JSFunction::Call(info); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult); + if (lightweightset->GetSize() != length) { // prevent length change + length = lightweightset->GetSize(); + } } return JSTaggedValue::Undefined(); }