mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-23 18:20:04 +00:00
HashMap HashSet LinkedList List ForEach IR
Use IR to save time and to avoid JSFunction::Call(). Issue: #I5Y9UV Signed-off-by: lichenshuai <lichenshuai@huawei.com> Change-Id: I54733053d39b3957d0a4789eb02f98cd19b5c394
This commit is contained in:
parent
55a6cbf81b
commit
39057c8849
@ -33,6 +33,10 @@ namespace panda::ecmascript::kungfu {
|
||||
V(DequeForEach) \
|
||||
V(LightWeightMapForEach) \
|
||||
V(LightWeightSetForEach) \
|
||||
V(HashMapForEach) \
|
||||
V(HashSetForEach) \
|
||||
V(LinkedListForEach) \
|
||||
V(ListForEach) \
|
||||
V(ArrayListForEach) \
|
||||
V(ArrayListReplaceAllElements) \
|
||||
|
||||
|
@ -643,6 +643,90 @@ DECLARE_BUILTINS(LightWeightSetForEach)
|
||||
Return(*res);
|
||||
}
|
||||
|
||||
DECLARE_BUILTINS(HashMapForEach)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
|
||||
|
||||
Label exit(env);
|
||||
Label slowPath(env);
|
||||
|
||||
ContainersStubBuilder containersBuilder(this);
|
||||
containersBuilder.ContainersHashCall(glue, thisValue, numArgs, &res, &exit,
|
||||
&slowPath, ContainersType::HASHMAP_FOREACH);
|
||||
Bind(&slowPath);
|
||||
{
|
||||
BUILDARG();
|
||||
res = CALLSLOWPATH();
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&exit);
|
||||
Return(*res);
|
||||
}
|
||||
|
||||
DECLARE_BUILTINS(HashSetForEach)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
|
||||
|
||||
Label exit(env);
|
||||
Label slowPath(env);
|
||||
|
||||
ContainersStubBuilder containersBuilder(this);
|
||||
containersBuilder.ContainersHashCall(glue, thisValue, numArgs, &res, &exit,
|
||||
&slowPath, ContainersType::HASHSET_FOREACH);
|
||||
Bind(&slowPath);
|
||||
{
|
||||
BUILDARG();
|
||||
res = CALLSLOWPATH();
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&exit);
|
||||
Return(*res);
|
||||
}
|
||||
|
||||
DECLARE_BUILTINS(LinkedListForEach)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
|
||||
|
||||
Label exit(env);
|
||||
Label slowPath(env);
|
||||
|
||||
ContainersStubBuilder containersBuilder(this);
|
||||
containersBuilder.ContainersLinkedListCall(glue, thisValue, numArgs, &res, &exit,
|
||||
&slowPath, ContainersType::LINKEDLIST_FOREACH);
|
||||
Bind(&slowPath);
|
||||
{
|
||||
BUILDARG();
|
||||
res = CALLSLOWPATH();
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&exit);
|
||||
Return(*res);
|
||||
}
|
||||
|
||||
DECLARE_BUILTINS(ListForEach)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
|
||||
|
||||
Label exit(env);
|
||||
Label slowPath(env);
|
||||
|
||||
ContainersStubBuilder containersBuilder(this);
|
||||
containersBuilder.ContainersLinkedListCall(glue, thisValue, numArgs, &res, &exit,
|
||||
&slowPath, ContainersType::LIST_FOREACH);
|
||||
Bind(&slowPath);
|
||||
{
|
||||
BUILDARG();
|
||||
res = CALLSLOWPATH();
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&exit);
|
||||
Return(*res);
|
||||
}
|
||||
|
||||
DECLARE_BUILTINS(ArrayListForEach)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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_HASHMAP_STUB_BUILDER_H
|
||||
#define ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_HASHMAP_STUB_BUILDER_H
|
||||
#include "ecmascript/compiler/stub_builder-inl.h"
|
||||
#include "ecmascript/js_api/js_api_hashmap.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class ContainersHashMapStubBuilder : public StubBuilder {
|
||||
public:
|
||||
explicit ContainersHashMapStubBuilder(StubBuilder *parent)
|
||||
: StubBuilder(parent) {}
|
||||
~ContainersHashMapStubBuilder() = default;
|
||||
NO_MOVE_SEMANTIC(ContainersHashMapStubBuilder);
|
||||
NO_COPY_SEMANTIC(ContainersHashMapStubBuilder);
|
||||
void GenerateCircuit() override {}
|
||||
|
||||
GateRef GetTableLength(GateRef obj)
|
||||
{
|
||||
GateRef tableOffset = IntPtr(JSAPIHashMap::HASHMAP_TABLE_INDEX);
|
||||
GateRef table = Load(VariableType::JS_POINTER(), obj, tableOffset);
|
||||
return GetLengthOfTaggedArray(table);
|
||||
}
|
||||
|
||||
GateRef GetNode(GateRef obj, GateRef index)
|
||||
{
|
||||
GateRef tableOffset = IntPtr(JSAPIHashMap::HASHMAP_TABLE_INDEX);
|
||||
GateRef table = Load(VariableType::JS_POINTER(), obj, tableOffset);
|
||||
return GetValueFromTaggedArray(table, index);
|
||||
}
|
||||
};
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_HASHMAP_STUB_BUILDER_H
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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_HASHSET_STUB_BUILDER_H
|
||||
#define ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_HASHSET_STUB_BUILDER_H
|
||||
#include "ecmascript/compiler/stub_builder-inl.h"
|
||||
#include "ecmascript/js_api/js_api_hashset.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class ContainersHashSetStubBuilder : public StubBuilder {
|
||||
public:
|
||||
explicit ContainersHashSetStubBuilder(StubBuilder *parent)
|
||||
: StubBuilder(parent) {}
|
||||
~ContainersHashSetStubBuilder() = default;
|
||||
NO_MOVE_SEMANTIC(ContainersHashSetStubBuilder);
|
||||
NO_COPY_SEMANTIC(ContainersHashSetStubBuilder);
|
||||
void GenerateCircuit() override {}
|
||||
|
||||
GateRef GetTableLength(GateRef obj)
|
||||
{
|
||||
GateRef tableOffset = IntPtr(JSAPIHashSet::HASHSET_TABLE_INDEX);
|
||||
GateRef table = Load(VariableType::JS_POINTER(), obj, tableOffset);
|
||||
return GetLengthOfTaggedArray(table);
|
||||
}
|
||||
|
||||
GateRef GetNode(GateRef obj, GateRef index)
|
||||
{
|
||||
GateRef tableOffset = IntPtr(JSAPIHashSet::HASHSET_TABLE_INDEX);
|
||||
GateRef table = Load(VariableType::JS_POINTER(), obj, tableOffset);
|
||||
return GetValueFromTaggedArray(table, index);
|
||||
}
|
||||
};
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_HASHSET_STUB_BUILDER_H
|
@ -48,4 +48,4 @@ public:
|
||||
}
|
||||
};
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_VECTOR_STUB_BUILDER_H
|
||||
#endif // ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_LIGHTWEIGHTMAP_STUB_BUILDER_H
|
@ -46,4 +46,4 @@ public:
|
||||
}
|
||||
};
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_VECTOR_STUB_BUILDER_H
|
||||
#endif // ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_LIGHTWEIGHTSET_STUB_BUILDER_H
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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_LINKEDLIST_STUB_BUILDER_H
|
||||
#define ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_LINKEDLIST_STUB_BUILDER_H
|
||||
#include "ecmascript/compiler/stub_builder-inl.h"
|
||||
#include "ecmascript/js_api/js_api_linked_list.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class ContainersLinkedListStubBuilder : public StubBuilder {
|
||||
public:
|
||||
explicit ContainersLinkedListStubBuilder(StubBuilder *parent)
|
||||
: StubBuilder(parent) {}
|
||||
~ContainersLinkedListStubBuilder() = default;
|
||||
NO_MOVE_SEMANTIC(ContainersLinkedListStubBuilder);
|
||||
NO_COPY_SEMANTIC(ContainersLinkedListStubBuilder);
|
||||
void GenerateCircuit() override {}
|
||||
|
||||
GateRef GetTableLength(GateRef obj)
|
||||
{
|
||||
GateRef tableOffset = IntPtr(JSAPILinkedList::DOUBLE_LIST_OFFSET);
|
||||
GateRef table = Load(VariableType::JS_POINTER(), obj, tableOffset);
|
||||
GateRef value = GetValueFromTaggedArray(table, Int32(TaggedDoubleList::NUMBER_OF_NODE_INDEX));
|
||||
return TaggedGetInt(value);
|
||||
}
|
||||
|
||||
GateRef GetNode(GateRef obj, GateRef index)
|
||||
{
|
||||
GateRef tableOffset = IntPtr(JSAPILinkedList::DOUBLE_LIST_OFFSET);
|
||||
GateRef table = Load(VariableType::JS_POINTER(), obj, tableOffset);
|
||||
return GetValueFromTaggedArray(table, index);
|
||||
}
|
||||
};
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_LINKEDLIST_STUB_BUILDER_H
|
47
ecmascript/compiler/builtins/containers_list_stub_builder.h
Normal file
47
ecmascript/compiler/builtins/containers_list_stub_builder.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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_LIST_STUB_BUILDER_H
|
||||
#define ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_LIST_STUB_BUILDER_H
|
||||
#include "ecmascript/compiler/stub_builder-inl.h"
|
||||
#include "ecmascript/js_api/js_api_list.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class ContainersListStubBuilder : public StubBuilder {
|
||||
public:
|
||||
explicit ContainersListStubBuilder(StubBuilder *parent)
|
||||
: StubBuilder(parent) {}
|
||||
~ContainersListStubBuilder() = default;
|
||||
NO_MOVE_SEMANTIC(ContainersListStubBuilder);
|
||||
NO_COPY_SEMANTIC(ContainersListStubBuilder);
|
||||
void GenerateCircuit() override {}
|
||||
|
||||
GateRef GetTableLength(GateRef obj)
|
||||
{
|
||||
GateRef tableOffset = IntPtr(JSAPIList::SINGLY_LIST_OFFSET);
|
||||
GateRef table = Load(VariableType::JS_POINTER(), obj, tableOffset);
|
||||
GateRef value = GetValueFromTaggedArray(table, Int32(TaggedSingleList::NUMBER_OF_NODE_INDEX));
|
||||
return TaggedGetInt(value);
|
||||
}
|
||||
|
||||
GateRef GetNode(GateRef obj, GateRef index)
|
||||
{
|
||||
GateRef tableOffset = IntPtr(JSAPIList::SINGLY_LIST_OFFSET);
|
||||
GateRef table = Load(VariableType::JS_POINTER(), obj, tableOffset);
|
||||
return GetValueFromTaggedArray(table, index);
|
||||
}
|
||||
};
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_LIST_STUB_BUILDER_H
|
@ -456,4 +456,247 @@ void ContainersStubBuilder::ContainersLightWeightCall(GateRef glue, GateRef this
|
||||
Bind(&afterLoop);
|
||||
Jump(exit);
|
||||
}
|
||||
|
||||
void ContainersStubBuilder::ContainersHashCall(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(node, 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 valueIsJSAPIHash(env);
|
||||
Label valueNotJSAPIHash(env);
|
||||
Label objIsJSProxy(env);
|
||||
Label objNotJSProxy(env);
|
||||
Label objIsJSAPIHash(env);
|
||||
Label thisArgUndefined(env);
|
||||
Label thisArgNotUndefined(env);
|
||||
Label callbackUndefined(env);
|
||||
Label callbackNotUndefined(env);
|
||||
Label nextCount(env);
|
||||
Label nodeNotHole(env);
|
||||
Label nodeIsLinked(env);
|
||||
Label nodeIsRBTree(env);
|
||||
Label loopLinked(env);
|
||||
Label loopHead(env);
|
||||
Label loopEnd(env);
|
||||
Label next(env);
|
||||
Label afterLoop(env);
|
||||
GateRef callbackFnHandle;
|
||||
Branch(IsContainer(*thisObj, type), &valueIsJSAPIHash, &valueNotJSAPIHash);
|
||||
Bind(&valueNotJSAPIHash);
|
||||
{
|
||||
Branch(IsJsProxy(*thisObj), &objIsJSProxy, &objNotJSProxy);
|
||||
Bind(&objIsJSProxy);
|
||||
{
|
||||
GateRef tempObj = GetTarget(*thisObj);
|
||||
Branch(IsContainer(tempObj, type), &objIsJSAPIHash, slowPath);
|
||||
Bind(&objIsJSAPIHash);
|
||||
{
|
||||
thisObj = tempObj;
|
||||
Jump(&valueIsJSAPIHash);
|
||||
}
|
||||
}
|
||||
Bind(&objNotJSProxy);
|
||||
Jump(slowPath);
|
||||
}
|
||||
Bind(&valueIsJSAPIHash);
|
||||
{
|
||||
Branch(Int64GreaterThanOrEqual(IntPtr(0), numArgs), &callbackUndefined, &callbackNotUndefined);
|
||||
Bind(&callbackUndefined);
|
||||
Jump(slowPath);
|
||||
Bind(&callbackNotUndefined);
|
||||
{
|
||||
Label isCall(env);
|
||||
Label notCall(env);
|
||||
Label isHeapObj(env);
|
||||
callbackFnHandle = GetCallArg0();
|
||||
Branch(TaggedIsHeapObject(callbackFnHandle), &isHeapObj, ¬Call);
|
||||
Bind(&isHeapObj);
|
||||
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 hasExceptionLinked(env);
|
||||
Label notHasExceptionLinked(env);
|
||||
Label hasExceptionRBTree(env);
|
||||
Label notHasExceptionRBTree(env);
|
||||
Branch(Int32LessThan(*index, *length), &next, &afterLoop);
|
||||
Bind(&next);
|
||||
{
|
||||
node = ContainerGetNode(*thisObj, *index, type);
|
||||
Branch(TaggedIsHole(*node), &loopEnd, &nodeNotHole);
|
||||
Bind(&nodeNotHole);
|
||||
Branch(IsLinkedNode(*node), &nodeIsLinked, &nodeIsRBTree);
|
||||
LoopBegin(&nodeIsLinked);
|
||||
{
|
||||
value = Load(VariableType::JS_POINTER(), *node, IntPtr(
|
||||
type == ContainersType::HASHSET_FOREACH ? LinkedNode::KEY_OFFSET : LinkedNode::VALUE_OFFSET));
|
||||
key = Load(VariableType::JS_POINTER(), *node, IntPtr(LinkedNode::KEY_OFFSET));
|
||||
GateRef retValue = JSCallDispatch(glue, callbackFnHandle, Int32(3), 0, // 3: numArgs
|
||||
JSCallMode::CALL_THIS_ARG3_WITH_RETURN, { *thisArg, *value, *key, *thisObj });
|
||||
Branch(HasPendingException(glue), &hasExceptionLinked, ¬HasExceptionLinked);
|
||||
Bind(&hasExceptionLinked);
|
||||
{
|
||||
result->WriteVariable(retValue);
|
||||
Jump(exit);
|
||||
}
|
||||
Bind(¬HasExceptionLinked);
|
||||
node = Load(VariableType::JS_POINTER(), *node, IntPtr(LinkedNode::NEXT_OFFSET));
|
||||
Branch(TaggedIsHole(*node), &loopEnd, &loopLinked);
|
||||
}
|
||||
Bind(&loopLinked);
|
||||
LoopEnd(&nodeIsLinked);
|
||||
Bind(&nodeIsRBTree);
|
||||
{
|
||||
GateRef retValue = CallRuntime(glue, RTSTUB_ID(ContainerRBTreeForEach),
|
||||
{ *node, callbackFnHandle, *thisArg, *thisObj,
|
||||
IntToTaggedInt(Int32(static_cast<int32_t>(type))) });
|
||||
Branch(HasPendingException(glue), &hasExceptionRBTree, ¬HasExceptionRBTree);
|
||||
Bind(&hasExceptionRBTree);
|
||||
{
|
||||
result->WriteVariable(retValue);
|
||||
Jump(exit);
|
||||
}
|
||||
Bind(¬HasExceptionRBTree);
|
||||
Jump(&loopEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
Bind(&loopEnd);
|
||||
index = Int32Add(*index, Int32(1));
|
||||
LoopEnd(&loopHead);
|
||||
}
|
||||
Bind(&afterLoop);
|
||||
Jump(exit);
|
||||
}
|
||||
|
||||
void ContainersStubBuilder::ContainersLinkedListCall(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(valueNode, VariableType::INT32(), Int32(0));
|
||||
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 valueIsJSAPILinkedList(env);
|
||||
Label valueNotJSAPILinkedList(env);
|
||||
Label objIsJSProxy(env);
|
||||
Label objNotJSProxy(env);
|
||||
Label objIsJSAPILinkedList(env);
|
||||
Label thisArgUndefined(env);
|
||||
Label thisArgNotUndefined(env);
|
||||
Label callbackUndefined(env);
|
||||
Label callbackNotUndefined(env);
|
||||
Label nextCount(env);
|
||||
Label valueNotHole(env);
|
||||
Label loopHead(env);
|
||||
Label loopEnd(env);
|
||||
Label next(env);
|
||||
Label afterLoop(env);
|
||||
GateRef callbackFnHandle;
|
||||
Branch(IsContainer(*thisObj, type), &valueIsJSAPILinkedList, &valueNotJSAPILinkedList);
|
||||
Bind(&valueNotJSAPILinkedList);
|
||||
{
|
||||
Branch(IsJsProxy(*thisObj), &objIsJSProxy, &objNotJSProxy);
|
||||
Bind(&objIsJSProxy);
|
||||
{
|
||||
GateRef tempObj = GetTarget(*thisObj);
|
||||
Branch(IsContainer(tempObj, type), &objIsJSAPILinkedList, slowPath);
|
||||
Bind(&objIsJSAPILinkedList);
|
||||
{
|
||||
thisObj = tempObj;
|
||||
Jump(&valueIsJSAPILinkedList);
|
||||
}
|
||||
}
|
||||
Bind(&objNotJSProxy);
|
||||
Jump(slowPath);
|
||||
}
|
||||
Bind(&valueIsJSAPILinkedList);
|
||||
{
|
||||
Branch(Int64GreaterThanOrEqual(IntPtr(0), numArgs), &callbackUndefined, &callbackNotUndefined);
|
||||
Bind(&callbackUndefined);
|
||||
Jump(slowPath);
|
||||
Bind(&callbackNotUndefined);
|
||||
{
|
||||
Label isCall(env);
|
||||
Label notCall(env);
|
||||
Label isHeapObj(env);
|
||||
callbackFnHandle = GetCallArg0();
|
||||
Branch(TaggedIsHeapObject(callbackFnHandle), &isHeapObj, ¬Call);
|
||||
Bind(&isHeapObj);
|
||||
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);
|
||||
valueNode = Int32(TaggedList<TaggedArray>::ELEMENTS_START_INDEX);
|
||||
Jump(&loopHead);
|
||||
LoopBegin(&loopHead);
|
||||
{
|
||||
Label hasException(env);
|
||||
Label notHasException(env);
|
||||
Branch(Int32LessThan(*index, *length), &next, &afterLoop);
|
||||
Bind(&next);
|
||||
{
|
||||
valueNode = TaggedGetInt(ContainerGetNode(*thisObj,
|
||||
Int32Add(*valueNode, Int32(TaggedList<TaggedArray>::NEXT_PTR_OFFSET)), type));
|
||||
value = ContainerGetNode(*thisObj, *valueNode, type);
|
||||
Branch(TaggedIsHole(*value), &loopEnd, &valueNotHole);
|
||||
Bind(&valueNotHole);
|
||||
key = IntToTaggedInt(*index);
|
||||
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);
|
||||
Jump(&loopEnd);
|
||||
}
|
||||
}
|
||||
Bind(&loopEnd);
|
||||
index = Int32Add(*index, Int32(1));
|
||||
LoopEnd(&loopHead);
|
||||
}
|
||||
Bind(&afterLoop);
|
||||
Jump(exit);
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
@ -17,8 +17,12 @@
|
||||
#define ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_STUB_BUILDER_H
|
||||
#include "ecmascript/compiler/builtins/containers_arraylist_stub_builder.h"
|
||||
#include "ecmascript/compiler/builtins/containers_deque_stub_builder.h"
|
||||
#include "ecmascript/compiler/builtins/containers_hashmap_stub_builder.h"
|
||||
#include "ecmascript/compiler/builtins/containers_hashset_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_linkedlist_stub_builder.h"
|
||||
#include "ecmascript/compiler/builtins/containers_list_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"
|
||||
@ -37,6 +41,10 @@ enum class ContainersType : uint8_t {
|
||||
DEQUE_FOREACH,
|
||||
LIGHTWEIGHTMAP_FOREACH,
|
||||
LIGHTWEIGHTSET_FOREACH,
|
||||
HASHMAP_FOREACH,
|
||||
HASHSET_FOREACH,
|
||||
LINKEDLIST_FOREACH,
|
||||
LIST_FOREACH,
|
||||
ARRAYLIST_FOREACH,
|
||||
ARRAYLIST_REPLACEALLELEMENTS,
|
||||
};
|
||||
@ -62,6 +70,12 @@ public:
|
||||
void ContainersLightWeightCall(GateRef glue, GateRef thisValue, GateRef numArgs,
|
||||
Variable* result, Label *exit, Label *slowPath, ContainersType type);
|
||||
|
||||
void ContainersHashCall(GateRef glue, GateRef thisValue, GateRef numArgs,
|
||||
Variable* result, Label *exit, Label *slowPath, ContainersType type);
|
||||
|
||||
void ContainersLinkedListCall(GateRef glue, GateRef thisValue, GateRef numArgs,
|
||||
Variable* result, Label *exit, Label *slowPath, ContainersType type);
|
||||
|
||||
GateRef IsContainer(GateRef obj, ContainersType type)
|
||||
{
|
||||
switch (type) {
|
||||
@ -80,6 +94,14 @@ public:
|
||||
return IsJSAPILightWeightMap(obj);
|
||||
case ContainersType::LIGHTWEIGHTSET_FOREACH:
|
||||
return IsJSAPILightWeightSet(obj);
|
||||
case ContainersType::HASHMAP_FOREACH:
|
||||
return IsJSAPIHashMap(obj);
|
||||
case ContainersType::HASHSET_FOREACH:
|
||||
return IsJSAPIHashSet(obj);
|
||||
case ContainersType::LINKEDLIST_FOREACH:
|
||||
return IsJSAPILinkedList(obj);
|
||||
case ContainersType::LIST_FOREACH:
|
||||
return IsJSAPIList(obj);
|
||||
case ContainersType::ARRAYLIST_FOREACH:
|
||||
case ContainersType::ARRAYLIST_REPLACEALLELEMENTS:
|
||||
return IsJSAPIArrayList(obj);
|
||||
@ -177,6 +199,22 @@ public:
|
||||
ContainersLightWeightSetStubBuilder lightWeightSetBuilder(this);
|
||||
return lightWeightSetBuilder.GetSize(obj);
|
||||
}
|
||||
case ContainersType::HASHMAP_FOREACH: {
|
||||
ContainersHashMapStubBuilder hashMapBuilder(this);
|
||||
return hashMapBuilder.GetTableLength(obj);
|
||||
}
|
||||
case ContainersType::HASHSET_FOREACH: {
|
||||
ContainersHashSetStubBuilder hashSetBuilder(this);
|
||||
return hashSetBuilder.GetTableLength(obj);
|
||||
}
|
||||
case ContainersType::LINKEDLIST_FOREACH: {
|
||||
ContainersLinkedListStubBuilder linkedListBuilder(this);
|
||||
return linkedListBuilder.GetTableLength(obj);
|
||||
}
|
||||
case ContainersType::LIST_FOREACH: {
|
||||
ContainersListStubBuilder listBuilder(this);
|
||||
return listBuilder.GetTableLength(obj);
|
||||
}
|
||||
case ContainersType::ARRAYLIST_REPLACEALLELEMENTS:
|
||||
case ContainersType::ARRAYLIST_FOREACH: {
|
||||
ContainersArrayListStubBuilder arrayListBuilder(this);
|
||||
@ -248,6 +286,31 @@ public:
|
||||
return False();
|
||||
}
|
||||
|
||||
GateRef ContainerGetNode(GateRef obj, GateRef index, ContainersType type)
|
||||
{
|
||||
switch (type) {
|
||||
case ContainersType::HASHMAP_FOREACH: {
|
||||
ContainersHashMapStubBuilder hashMapBuilder(this);
|
||||
return hashMapBuilder.GetNode(obj, index);
|
||||
}
|
||||
case ContainersType::HASHSET_FOREACH: {
|
||||
ContainersHashSetStubBuilder hashSetBuilder(this);
|
||||
return hashSetBuilder.GetNode(obj, index);
|
||||
}
|
||||
case ContainersType::LINKEDLIST_FOREACH: {
|
||||
ContainersLinkedListStubBuilder linkedListBuilder(this);
|
||||
return linkedListBuilder.GetNode(obj, index);
|
||||
}
|
||||
case ContainersType::LIST_FOREACH: {
|
||||
ContainersListStubBuilder listBuilder(this);
|
||||
return listBuilder.GetNode(obj, index);
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return False();
|
||||
}
|
||||
|
||||
GateRef PlainArrayGetKey(GateRef obj, GateRef index)
|
||||
{
|
||||
ContainersPlainArrayStubBuilder plainArrayBuilder(this);
|
||||
|
@ -1092,6 +1092,36 @@ inline GateRef StubBuilder::IsJSAPILightWeightSet(GateRef obj)
|
||||
return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_API_LIGHT_WEIGHT_SET)));
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::IsLinkedNode(GateRef obj)
|
||||
{
|
||||
GateRef objectType = GetObjectType(LoadHClass(obj));
|
||||
return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::LINKED_NODE)));
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::IsJSAPIHashMap(GateRef obj)
|
||||
{
|
||||
GateRef objectType = GetObjectType(LoadHClass(obj));
|
||||
return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_API_HASH_MAP)));
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::IsJSAPIHashSet(GateRef obj)
|
||||
{
|
||||
GateRef objectType = GetObjectType(LoadHClass(obj));
|
||||
return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_API_HASH_SET)));
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::IsJSAPILinkedList(GateRef obj)
|
||||
{
|
||||
GateRef objectType = GetObjectType(LoadHClass(obj));
|
||||
return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_API_LINKED_LIST)));
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::IsJSAPIList(GateRef obj)
|
||||
{
|
||||
GateRef objectType = GetObjectType(LoadHClass(obj));
|
||||
return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_API_LIST)));
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::IsJSAPIArrayList(GateRef obj)
|
||||
{
|
||||
GateRef objectType = GetObjectType(LoadHClass(obj));
|
||||
|
@ -261,8 +261,13 @@ public:
|
||||
GateRef IsJSAPIPlainArray(GateRef obj);
|
||||
GateRef IsJSAPIQueue(GateRef obj);
|
||||
GateRef IsJSAPIDeque(GateRef obj);
|
||||
GateRef IsJSAPILightWeightMap(GateRef attr);
|
||||
GateRef IsJSAPILightWeightSet(GateRef attr);
|
||||
GateRef IsJSAPILightWeightMap(GateRef obj);
|
||||
GateRef IsJSAPILightWeightSet(GateRef obj);
|
||||
GateRef IsLinkedNode(GateRef obj);
|
||||
GateRef IsJSAPIHashMap(GateRef obj);
|
||||
GateRef IsJSAPIHashSet(GateRef obj);
|
||||
GateRef IsJSAPILinkedList(GateRef obj);
|
||||
GateRef IsJSAPIList(GateRef obj);
|
||||
GateRef IsJSAPIArrayList(GateRef obj);
|
||||
GateRef GetTarget(GateRef proxyObj);
|
||||
GateRef HandlerBaseIsAccessor(GateRef attr);
|
||||
|
@ -269,9 +269,9 @@ JSTaggedValue ContainersHashSet::ForEach(EcmaRuntimeCallInfo *argv)
|
||||
currentKey.Update(node->GetKey());
|
||||
EcmaRuntimeCallInfo *info =
|
||||
EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle,
|
||||
thisArgHandle, undefined, 2); // 2: two args
|
||||
thisArgHandle, undefined, 3); // 3: three args
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
info->SetCallArg(currentKey.GetTaggedValue(), thisHandle.GetTaggedValue());
|
||||
info->SetCallArg(currentKey.GetTaggedValue(), currentKey.GetTaggedValue(), thisHandle.GetTaggedValue());
|
||||
JSTaggedValue funcResult = JSFunction::Call(info);
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult);
|
||||
}
|
||||
|
@ -980,7 +980,8 @@ JSHandle<JSTaggedValue> ContainersPrivate::InitializeList(JSThread *thread)
|
||||
SetFrozenFunction(thread, listFuncPrototype, "getIndexOf", ContainersList::GetIndexOf, FuncLength::ONE);
|
||||
SetFrozenFunction(thread, listFuncPrototype, "getLastIndexOf", ContainersList::GetLastIndexOf, FuncLength::ONE);
|
||||
SetFrozenFunction(thread, listFuncPrototype, "set", ContainersList::Set, FuncLength::ONE);
|
||||
SetFrozenFunction(thread, listFuncPrototype, "forEach", ContainersList::ForEach, FuncLength::ONE);
|
||||
SetFrozenFunction(thread, listFuncPrototype, "forEach", ContainersList::ForEach, FuncLength::ONE,
|
||||
static_cast<uint8_t>(BUILTINS_STUB_ID(ListForEach)));
|
||||
SetFrozenFunction(thread, listFuncPrototype, "replaceAllElements", ContainersList::ReplaceAllElements,
|
||||
FuncLength::ONE);
|
||||
SetFrozenFunction(thread, listFuncPrototype, "equal", ContainersList::Equal, FuncLength::ONE);
|
||||
@ -1042,7 +1043,8 @@ JSHandle<JSTaggedValue> ContainersPrivate::InitializeLinkedList(JSThread *thread
|
||||
SetFrozenFunction(thread, linkedListFuncPrototype, "convertToArray", ContainersLinkedList::ConvertToArray,
|
||||
FuncLength::ONE);
|
||||
SetFrozenFunction(thread, linkedListFuncPrototype, "set", ContainersLinkedList::Set, FuncLength::ONE);
|
||||
SetFrozenFunction(thread, linkedListFuncPrototype, "forEach", ContainersLinkedList::ForEach, FuncLength::ONE);
|
||||
SetFrozenFunction(thread, linkedListFuncPrototype, "forEach", ContainersLinkedList::ForEach, FuncLength::ONE,
|
||||
static_cast<uint8_t>(BUILTINS_STUB_ID(LinkedListForEach)));
|
||||
|
||||
JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersLinkedList::Length, "length",
|
||||
FuncLength::ZERO);
|
||||
@ -1114,7 +1116,8 @@ JSHandle<JSTaggedValue> ContainersPrivate::InitializeHashMap(JSThread *thread)
|
||||
// HashMap.prototype.get()
|
||||
SetFrozenFunction(thread, hashMapFuncPrototype, "get", ContainersHashMap::Get, FuncLength::ONE);
|
||||
// HashMap.prototype.forEach()
|
||||
SetFrozenFunction(thread, hashMapFuncPrototype, "forEach", ContainersHashMap::ForEach, FuncLength::TWO);
|
||||
SetFrozenFunction(thread, hashMapFuncPrototype, "forEach", ContainersHashMap::ForEach, FuncLength::TWO,
|
||||
static_cast<uint8_t>(BUILTINS_STUB_ID(HashMapForEach)));
|
||||
// HashMap.prototype.hasKey()
|
||||
SetFrozenFunction(thread, hashMapFuncPrototype, "hasKey", ContainersHashMap::HasKey, FuncLength::ONE);
|
||||
// HashMap.prototype.hasValue()
|
||||
@ -1190,7 +1193,8 @@ JSHandle<JSTaggedValue> ContainersPrivate::InitializeHashSet(JSThread *thread)
|
||||
SetFrozenFunction(thread, hashSetFuncPrototype, "clear", ContainersHashSet::Clear, FuncLength::ZERO);
|
||||
SetFrozenFunction(thread, hashSetFuncPrototype, "values", ContainersHashSet::Values, FuncLength::ZERO);
|
||||
SetFrozenFunction(thread, hashSetFuncPrototype, "entries", ContainersHashSet::Entries, FuncLength::ZERO);
|
||||
SetFrozenFunction(thread, hashSetFuncPrototype, "forEach", ContainersHashSet::ForEach, FuncLength::TWO);
|
||||
SetFrozenFunction(thread, hashSetFuncPrototype, "forEach", ContainersHashSet::ForEach, FuncLength::TWO,
|
||||
static_cast<uint8_t>(BUILTINS_STUB_ID(HashSetForEach)));
|
||||
|
||||
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
||||
// @@ToStringTag
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "ecmascript/accessor_data.h"
|
||||
#include "ecmascript/base/number_helper.h"
|
||||
#include "ecmascript/base/string_helper.h"
|
||||
#include "ecmascript/compiler/builtins/containers_stub_builder.h"
|
||||
#include "ecmascript/compiler/call_signature.h"
|
||||
#include "ecmascript/compiler/ecma_opcode_des.h"
|
||||
#include "ecmascript/compiler/rt_call_signature.h"
|
||||
@ -44,6 +45,7 @@
|
||||
#include "ecmascript/message_string.h"
|
||||
#include "ecmascript/object_factory.h"
|
||||
#include "ecmascript/tagged_dictionary.h"
|
||||
#include "ecmascript/tagged_node.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
#include "libpandafile/bytecode_instruction-inl.h"
|
||||
|
||||
@ -2055,6 +2057,44 @@ DEF_RUNTIME_STUBS(LdObjByName)
|
||||
return RuntimeLdObjByName(thread, receiver, propKey, callGetter, undefined).GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_STUBS(ContainerRBTreeForEach)
|
||||
{
|
||||
RUNTIME_STUBS_HEADER(ContainerRBTreeForEach);
|
||||
JSHandle<JSTaggedValue> node = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: param index
|
||||
JSHandle<JSTaggedValue> callbackFnHandle = GetHArg<JSTaggedValue>(argv, argc, 1); // 1: param index
|
||||
JSHandle<JSTaggedValue> thisArgHandle = GetHArg<JSTaggedValue>(argv, argc, 2); // 2: param index
|
||||
JSHandle<JSTaggedValue> thisHandle = GetHArg<JSTaggedValue>(argv, argc, 3); // 3: param index
|
||||
JSHandle<JSTaggedValue> type = GetHArg<JSTaggedValue>(argv, argc, 4); // 4: param index
|
||||
|
||||
ASSERT(node->IsRBTreeNode());
|
||||
ASSERT(callbackFnHandle->IsCallable());
|
||||
ASSERT(type->IsInt());
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
auto containersType = static_cast<kungfu::ContainersType>(type->GetInt());
|
||||
JSMutableHandle<TaggedQueue> queue(thread, thread->GetEcmaVM()->GetFactory()->NewTaggedQueue(0));
|
||||
JSMutableHandle<RBTreeNode> treeNode(thread, JSTaggedValue::Undefined());
|
||||
queue.Update(JSTaggedValue(TaggedQueue::Push(thread, queue, node)));
|
||||
while (!queue->Empty()) {
|
||||
treeNode.Update(queue->Pop(thread));
|
||||
EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle,
|
||||
undefined, 3); // 3: three args
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData());
|
||||
info->SetCallArg(containersType == kungfu::ContainersType::HASHSET_FOREACH ?
|
||||
treeNode->GetKey() : treeNode->GetValue(), treeNode->GetKey(), thisHandle.GetTaggedValue());
|
||||
JSTaggedValue funcResult = JSFunction::Call(info);
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult.GetRawData());
|
||||
if (!treeNode->GetLeft().IsHole()) {
|
||||
JSHandle<JSTaggedValue> left(thread, treeNode->GetLeft());
|
||||
queue.Update(JSTaggedValue(TaggedQueue::Push(thread, queue, left)));
|
||||
}
|
||||
if (!treeNode->GetRight().IsHole()) {
|
||||
JSHandle<JSTaggedValue> right(thread, treeNode->GetRight());
|
||||
queue.Update(JSTaggedValue(TaggedQueue::Push(thread, queue, right)));
|
||||
}
|
||||
}
|
||||
return JSTaggedValue::True().GetRawData();
|
||||
}
|
||||
|
||||
JSTaggedType RuntimeStubs::CreateArrayFromList([[maybe_unused]]uintptr_t argGlue, int32_t argc, JSTaggedValue *argvPtr)
|
||||
{
|
||||
auto thread = JSThread::GlueToJSThread(argGlue);
|
||||
|
@ -292,7 +292,8 @@ using JSFunctionReentry = JSTaggedValue (*)(uintptr_t glue, uint32_t argc, const
|
||||
V(LdPatchVar) \
|
||||
V(StPatchVar) \
|
||||
V(LdObjByName) \
|
||||
V(DeoptHandler)
|
||||
V(DeoptHandler) \
|
||||
V(ContainerRBTreeForEach)
|
||||
|
||||
#define RUNTIME_STUB_LIST(V) \
|
||||
RUNTIME_ASM_STUB_LIST(V) \
|
||||
|
@ -165,6 +165,31 @@ if (globalThis["ArkPrivate"] != undefined) {
|
||||
}
|
||||
}
|
||||
res.forEach(elements);
|
||||
|
||||
// test RBTree
|
||||
let collisionMap = new fastmap();
|
||||
let count = 0;
|
||||
// same hash when mod 1024
|
||||
collisionMap.set(1224, 1);
|
||||
collisionMap.set(1285, 2);
|
||||
collisionMap.set(1463, 3);
|
||||
collisionMap.set(4307, 4);
|
||||
collisionMap.set(5135, 5);
|
||||
collisionMap.set(5903, 6);
|
||||
collisionMap.set(6603, 7);
|
||||
collisionMap.set(6780, 8);
|
||||
collisionMap.set(8416, 9);
|
||||
collisionMap.set(9401, 10);
|
||||
collisionMap.set(9740, 11);
|
||||
collisionMap.forEach((value, key, hashMap) => {
|
||||
if (hashMap.get(key) == value) {
|
||||
count += value;
|
||||
}
|
||||
});
|
||||
if (count != 66) { // 66: 1 + 2 + 3 + ... + 11
|
||||
print("test RBTree forEach fail. count=" + count);
|
||||
}
|
||||
|
||||
if (!flag) {
|
||||
print("Test HashMap success!!!");
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user