reason:add queue deque stack plainarray and fix queue bug

description:add queue deque stack plainarray and fix queue bug
issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I5XGLR?from=project-issue

Signed-off-by: wupengyong <wupengyong@huawei.com>
Change-Id: I9f27e3d65e31817bf5524419078f08868869c12a
This commit is contained in:
wupengyong 2022-10-24 21:04:12 +08:00
parent 8a0b818b73
commit 7e6660bad8
15 changed files with 719 additions and 13 deletions

View File

@ -27,6 +27,10 @@ namespace panda::ecmascript::kungfu {
V(CharAt) \
V(VectorForEach) \
V(VectorReplaceAllElements) \
V(StackForEach) \
V(PlainArrayForEach) \
V(QueueForEach) \
V(DequeForEach) \
class BuiltinsStubCSigns {
public:

View File

@ -516,4 +516,88 @@ DECLARE_BUILTINS(VectorReplaceAllElements)
Bind(&exit);
Return(*res);
}
DECLARE_BUILTINS(StackForEach)
{
auto env = GetEnvironment();
DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
Label exit(env);
Label slowPath(env);
ContainersStubBuilder containersBuilder(this);
containersBuilder.ContainersCommonFuncCall(glue, thisValue, numArgs, &res, &exit,
&slowPath, ContainersType::STACK_FOREACH);
Bind(&slowPath);
{
BUILDARG();
res = CALLSLOWPATH();
Jump(&exit);
}
Bind(&exit);
Return(*res);
}
DECLARE_BUILTINS(PlainArrayForEach)
{
auto env = GetEnvironment();
DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
Label exit(env);
Label slowPath(env);
ContainersStubBuilder containersBuilder(this);
containersBuilder.ContainersCommonFuncCall(glue, thisValue, numArgs, &res, &exit,
&slowPath, ContainersType::PLAINARRAY_FOREACH);
Bind(&slowPath);
{
BUILDARG();
res = CALLSLOWPATH();
Jump(&exit);
}
Bind(&exit);
Return(*res);
}
DECLARE_BUILTINS(QueueForEach)
{
auto env = GetEnvironment();
DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
Label exit(env);
Label slowPath(env);
ContainersStubBuilder containersBuilder(this);
containersBuilder.QueueCommonFuncCall(glue, thisValue, numArgs, &res, &exit,
&slowPath, ContainersType::QUEUE_FOREACH);
Bind(&slowPath);
{
BUILDARG();
res = CALLSLOWPATH();
Jump(&exit);
}
Bind(&exit);
Return(*res);
}
DECLARE_BUILTINS(DequeForEach)
{
auto env = GetEnvironment();
DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
Label exit(env);
Label slowPath(env);
ContainersStubBuilder containersBuilder(this);
containersBuilder.DequeCommonFuncCall(glue, thisValue, numArgs, &res, &exit,
&slowPath, ContainersType::DEQUE_FOREACH);
Bind(&slowPath);
{
BUILDARG();
res = CALLSLOWPATH();
Jump(&exit);
}
Bind(&exit);
Return(*res);
}
} // namespace panda::ecmascript::kungfu

View File

@ -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.
*/
#ifndef ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_DEQUE_STUB_BUILDER_H
#define ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_DEQUE_STUB_BUILDER_H
#include "ecmascript/compiler/stub_builder-inl.h"
#include "ecmascript/js_api/js_api_deque.h"
namespace panda::ecmascript::kungfu {
class ContainersDequeStubBuilder : public StubBuilder {
public:
explicit ContainersDequeStubBuilder(StubBuilder *parent)
: StubBuilder(parent) {}
~ContainersDequeStubBuilder() = default;
NO_MOVE_SEMANTIC(ContainersDequeStubBuilder);
NO_COPY_SEMANTIC(ContainersDequeStubBuilder);
void GenerateCircuit() override {}
GateRef GetSize(GateRef obj)
{
GateRef elementsOffset = IntPtr(JSObject::ELEMENTS_OFFSET);
GateRef elements = Load(VariableType::JS_POINTER(), obj, elementsOffset);
GateRef capacity = Load(VariableType::INT32(), elements, IntPtr(TaggedArray::LENGTH_OFFSET));
GateRef first = GetFirst(obj);
GateRef last = GetLast(obj);
return Int32Mod(Int32Add(Int32Sub(last, first), capacity), capacity);
}
GateRef Get(GateRef obj, GateRef index)
{
GateRef elementsOffset = IntPtr(JSObject::ELEMENTS_OFFSET);
GateRef elements = Load(VariableType::JS_POINTER(), obj, elementsOffset);
GateRef capacity = Load(VariableType::INT32(), elements, IntPtr(TaggedArray::LENGTH_OFFSET));
GateRef first = GetFirst(obj);
GateRef curIndex = Int32Mod(Int32Add(first, index), capacity);
return GetValueFromTaggedArray(elements, curIndex);
}
GateRef GetFirst(GateRef obj)
{
return Load(VariableType::INT32(), obj, IntPtr(JSAPIDeque::FIRST_OFFSET));
}
GateRef GetLast(GateRef obj)
{
return Load(VariableType::INT32(), obj, IntPtr(JSAPIDeque::LAST_OFFSET));
}
GateRef GetElementsLength(GateRef obj)
{
GateRef elementsOffset = IntPtr(JSObject::ELEMENTS_OFFSET);
GateRef elements = Load(VariableType::JS_POINTER(), obj, elementsOffset);
return Load(VariableType::INT32(), elements, IntPtr(TaggedArray::LENGTH_OFFSET));
}
};
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_DEQUE_STUB_BUILDER_H

View File

@ -0,0 +1,56 @@
/*
* 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_PLAINARRAY_STUB_BUILDER_H
#define ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_PLAINARRAY_STUB_BUILDER_H
#include "ecmascript/compiler/stub_builder-inl.h"
#include "ecmascript/js_api/js_api_plain_array.h"
namespace panda::ecmascript::kungfu {
class ContainersPlainArrayStubBuilder : public StubBuilder {
public:
explicit ContainersPlainArrayStubBuilder(StubBuilder *parent)
: StubBuilder(parent) {}
~ContainersPlainArrayStubBuilder() = default;
NO_MOVE_SEMANTIC(ContainersPlainArrayStubBuilder);
NO_COPY_SEMANTIC(ContainersPlainArrayStubBuilder);
void GenerateCircuit() override {}
GateRef GetSize(GateRef obj)
{
return Load(VariableType::INT32(), obj, IntPtr(JSAPIPlainArray::LENGTH_OFFSET));
}
GateRef Get(GateRef obj, GateRef index)
{
GateRef elementsOffset = IntPtr(JSAPIPlainArray::VALUES_OFFSET);
GateRef elements = Load(VariableType::JS_POINTER(), obj, elementsOffset);
return GetValueFromTaggedArray(elements, index);
}
GateRef GetKey(GateRef obj, GateRef index)
{
GateRef elementsOffset = IntPtr(JSAPIPlainArray::KEYS_OFFSET);
GateRef elements = Load(VariableType::JS_POINTER(), obj, elementsOffset);
return GetValueFromTaggedArray(elements, index);
}
void Set(GateRef glue, GateRef obj, GateRef index, GateRef value)
{
GateRef elementsOffset = IntPtr(JSObject::ELEMENTS_OFFSET);
GateRef elements = Load(VariableType::JS_POINTER(), obj, elementsOffset);
SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, index, value);
}
};
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_PLAINARRAY_STUB_BUILDER_H

View File

@ -0,0 +1,86 @@
/*
* 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_QUEUE_STUB_BUILDER_H
#define ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_QUEUE_STUB_BUILDER_H
#include "ecmascript/compiler/stub_builder-inl.h"
#include "ecmascript/js_api/js_api_queue.h"
namespace panda::ecmascript::kungfu {
class ContainersQueueStubBuilder : public StubBuilder {
public:
explicit ContainersQueueStubBuilder(StubBuilder *parent)
: StubBuilder(parent) {}
~ContainersQueueStubBuilder() = default;
NO_MOVE_SEMANTIC(ContainersQueueStubBuilder);
NO_COPY_SEMANTIC(ContainersQueueStubBuilder);
void GenerateCircuit() override {}
GateRef GetArrayLength(GateRef obj)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
Label exit(env);
Label endGreatBeging(env);
Label endNotGreatBeging(env);
DEFVARIABLE(length, VariableType::INT32(), Int32(0));
GateRef begin = Load(VariableType::INT32(), obj, IntPtr(JSAPIQueue::FRONT_OFFSET));
GateRef end = Load(VariableType::INT32(), obj, IntPtr(JSAPIQueue::TAIL_OFFSET));
Branch(Int32GreaterThanOrEqual(end, begin), &endGreatBeging, &endNotGreatBeging);
Bind(&endGreatBeging);
{
length = Int32Sub(end, begin);
Jump(&exit);
}
Bind(&endNotGreatBeging);
{
GateRef elementsOffset = IntPtr(JSObject::ELEMENTS_OFFSET);
GateRef elements = Load(VariableType::JS_POINTER(), obj, elementsOffset);
GateRef elementsSize = Load(VariableType::INT32(), elements, IntPtr(TaggedArray::LENGTH_OFFSET));
length = Int32Add(Int32Sub(end, begin), elementsSize);
Jump(&exit);
}
Bind(&exit);
auto ret = *length;
env->SubCfgExit();
return ret;
}
GateRef Get(GateRef obj, GateRef index)
{
GateRef elementsOffset = IntPtr(JSObject::ELEMENTS_OFFSET);
GateRef elements = Load(VariableType::JS_POINTER(), obj, elementsOffset);
GateRef capacity = Load(VariableType::INT32(), elements, IntPtr(TaggedArray::LENGTH_OFFSET));
GateRef front = Load(VariableType::INT32(), obj, IntPtr(JSAPIQueue::FRONT_OFFSET));
GateRef curIndex = Int32Mod(Int32Add(front, index), capacity);
return GetValueFromTaggedArray(elements, curIndex);
}
GateRef GetNextPosition(GateRef obj, GateRef index)
{
GateRef elementsOffset = IntPtr(JSObject::ELEMENTS_OFFSET);
GateRef elements = Load(VariableType::JS_POINTER(), obj, elementsOffset);
GateRef elementsSize = Load(VariableType::INT32(), elements, IntPtr(TaggedArray::LENGTH_OFFSET));
return Int32Mod(Int32Add(index, Int32(1)), elementsSize);
}
GateRef GetCurrentFront(GateRef obj)
{
return Load(VariableType::INT32(), obj, IntPtr(JSAPIQueue::FRONT_OFFSET));
}
};
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_QUEUE_STUB_BUILDER_H

View File

@ -0,0 +1,50 @@
/*
* 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_STACK_STUB_BUILDER_H
#define ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_STACK_STUB_BUILDER_H
#include "ecmascript/compiler/stub_builder-inl.h"
#include "ecmascript/js_api/js_api_stack.h"
namespace panda::ecmascript::kungfu {
class ContainersStackStubBuilder : public StubBuilder {
public:
explicit ContainersStackStubBuilder(StubBuilder *parent)
: StubBuilder(parent) {}
~ContainersStackStubBuilder() = default;
NO_MOVE_SEMANTIC(ContainersStackStubBuilder);
NO_COPY_SEMANTIC(ContainersStackStubBuilder);
void GenerateCircuit() override {}
GateRef GetSize(GateRef obj)
{
GateRef top = Load(VariableType::INT32(), obj, IntPtr(JSAPIStack::TOP_OFFSET));
return Int32Add(top, Int32(1));
}
GateRef Get(GateRef obj, GateRef index)
{
GateRef elementsOffset = IntPtr(JSObject::ELEMENTS_OFFSET);
GateRef elements = Load(VariableType::JS_POINTER(), obj, elementsOffset);
return GetValueFromTaggedArray(elements, index);
}
void Set(GateRef glue, GateRef obj, GateRef index, GateRef value)
{
GateRef elementsOffset = IntPtr(JSObject::ELEMENTS_OFFSET);
GateRef elements = Load(VariableType::JS_POINTER(), obj, elementsOffset);
SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, index, value);
}
};
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_STACK_STUB_BUILDER_H

View File

@ -50,7 +50,7 @@ void ContainersStubBuilder::ContainersCommonFuncCall(GateRef glue, GateRef thisV
Bind(&objIsJSProxy);
{
GateRef tempObj = GetTarget(*thisObj);
Branch(IsJSAPIVector(tempObj), &objIsJSAPIVector, slowPath);
Branch(IsContainer(tempObj, type), &objIsJSAPIVector, slowPath);
Bind(&objIsJSAPIVector);
{
thisObj = tempObj;
@ -98,7 +98,11 @@ void ContainersStubBuilder::ContainersCommonFuncCall(GateRef glue, GateRef thisV
Bind(&next);
{
kValue = ContainerGetValue(*thisObj, *k, type);
key = IntToTaggedInt(*k);
if (IsPlainArray(type)) {
key = PlainArrayGetKey(*thisObj, *k);
} else {
key = IntToTaggedInt(*k);
}
GateRef retValue = JSCallDispatch(glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0,
JSCallMode::CALL_THIS_ARG3_WITH_RETURN, { *thisArg, *kValue, *key, *thisObj });
Branch(HasPendingException(glue), &hasException, &notHasException);
@ -127,4 +131,213 @@ void ContainersStubBuilder::ContainersCommonFuncCall(GateRef glue, GateRef thisV
Bind(&afterLoop);
Jump(exit);
}
void ContainersStubBuilder::QueueCommonFuncCall(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::INT64(), Int64(0));
DEFVARIABLE(kValue, VariableType::JS_ANY(), Undefined());
DEFVARIABLE(length, VariableType::INT32(), Int32(0));
DEFVARIABLE(k, VariableType::INT32(), Int32(0));
DEFVARIABLE(index, VariableType::INT32(), Int32(0));
Label valueIsJSAPIVector(env);
Label valueNotJSAPIVector(env);
Label objIsJSProxy(env);
Label objNotJSProxy(env);
Label objIsJSAPIVector(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), &valueIsJSAPIVector, &valueNotJSAPIVector);
Bind(&valueNotJSAPIVector);
{
Branch(IsJsProxy(*thisObj), &objIsJSProxy, &objNotJSProxy);
Bind(&objIsJSProxy);
{
GateRef tempObj = GetTarget(*thisObj);
Branch(IsContainer(tempObj, type), &objIsJSAPIVector, slowPath);
Bind(&objIsJSAPIVector);
{
thisObj = tempObj;
Jump(&valueIsJSAPIVector);
}
}
Bind(&objNotJSProxy);
Jump(slowPath);
}
Bind(&valueIsJSAPIVector);
{
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, &notCall);
Bind(&notCall);
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);
Label setValue(env);
Branch(Int32LessThan(*k, *length), &next, &afterLoop);
Bind(&next);
{
kValue = ContainerGetValue(*thisObj, *index, type);
index = QueueGetNextPosition(*thisObj, *index);
key = IntToTaggedInt(*k);
GateRef retValue = JSCallDispatch(glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0,
JSCallMode::CALL_THIS_ARG3_WITH_RETURN, { *thisArg, *kValue, *key, *thisObj });
Branch(HasPendingException(glue), &hasException, &notHasException);
Bind(&hasException);
{
result->WriteVariable(retValue);
Jump(exit);
}
Bind(&notHasException);
Jump(&loopEnd);
}
}
Bind(&loopEnd);
k = Int32Add(*k, Int32(1));
LoopEnd(&loopHead);
}
Bind(&afterLoop);
Jump(exit);
}
void ContainersStubBuilder::DequeCommonFuncCall(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::INT64(), Int64(0));
DEFVARIABLE(kValue, VariableType::JS_ANY(), Undefined());
DEFVARIABLE(length, VariableType::INT32(), Int32(0));
DEFVARIABLE(first, VariableType::INT32(), Int32(0));
DEFVARIABLE(index, VariableType::INT32(), Int32(0));
Label valueIsJSAPIVector(env);
Label valueNotJSAPIVector(env);
Label objIsJSProxy(env);
Label objNotJSProxy(env);
Label objIsJSAPIVector(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), &valueIsJSAPIVector, &valueNotJSAPIVector);
Bind(&valueNotJSAPIVector);
{
Branch(IsJsProxy(*thisObj), &objIsJSProxy, &objNotJSProxy);
Bind(&objIsJSProxy);
{
GateRef tempObj = GetTarget(*thisObj);
Branch(IsContainer(tempObj, type), &objIsJSAPIVector, slowPath);
Bind(&objIsJSAPIVector);
{
thisObj = tempObj;
Jump(&valueIsJSAPIVector);
}
}
Bind(&objNotJSProxy);
Jump(slowPath);
}
Bind(&valueIsJSAPIVector);
{
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, &notCall);
Bind(&notCall);
Jump(slowPath);
Bind(&isCall);
{
Branch(Int64GreaterThanOrEqual(IntPtr(1), numArgs), &thisArgUndefined, &thisArgNotUndefined);
Bind(&thisArgUndefined);
Jump(&nextCount);
Bind(&thisArgNotUndefined);
thisArg = GetCallArg1();
Jump(&nextCount);
}
}
}
Bind(&nextCount);
{
ContainersDequeStubBuilder dequeBuilder(this);
first = dequeBuilder.GetFirst(*thisObj);
GateRef last = dequeBuilder.GetLast(*thisObj);
GateRef capacity = dequeBuilder.GetElementsLength(*thisObj);
Jump(&loopHead);
LoopBegin(&loopHead);
{
Label lenChange(env);
Label hasException(env);
Label notHasException(env);
Label setValue(env);
Branch(Int32NotEqual(*first, last), &next, &afterLoop);
Bind(&next);
{
kValue = ContainerGetValue(*thisObj, *index, type);
key = IntToTaggedInt(*index);
GateRef retValue = JSCallDispatch(glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0,
JSCallMode::CALL_THIS_ARG3_WITH_RETURN, { *thisArg, *kValue, *key, *thisObj });
Branch(HasPendingException(glue), &hasException, &notHasException);
Bind(&hasException);
{
result->WriteVariable(retValue);
Jump(exit);
}
Bind(&notHasException);
Jump(&loopEnd);
}
}
Bind(&loopEnd);
first = Int32Mod(Int32Add(*first, Int32(1)), capacity);
index = Int32Add(*index, Int32(1));
LoopEnd(&loopHead);
}
Bind(&afterLoop);
Jump(exit);
}
} // namespace panda::ecmascript::kungfu

View File

@ -15,6 +15,10 @@
#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_plainarray_stub_builder.h"
#include "ecmascript/compiler/builtins/containers_queue_stub_builder.h"
#include "ecmascript/compiler/builtins/containers_stack_stub_builder.h"
#include "ecmascript/compiler/builtins/containers_vector_stub_builder.h"
#include "ecmascript/compiler/builtins/builtins_stubs.h"
#include "ecmascript/js_api/js_api_vector.h"
@ -24,6 +28,10 @@ namespace panda::ecmascript::kungfu {
enum class ContainersType : uint8_t {
VECTOR_FOREACH = 0,
VECTOR_REPLACEALLELEMENTS,
STACK_FOREACH,
PLAINARRAY_FOREACH,
QUEUE_FOREACH,
DEQUE_FOREACH,
};
class ContainersStubBuilder : public BuiltinsStubBuilder {
@ -38,12 +46,26 @@ public:
void ContainersCommonFuncCall(GateRef glue, GateRef thisValue, GateRef numArgs,
Variable* result, Label *exit, Label *slowPath, ContainersType type);
void QueueCommonFuncCall(GateRef glue, GateRef thisValue, GateRef numArgs,
Variable* result, Label *exit, Label *slowPath, ContainersType type);
void DequeCommonFuncCall(GateRef glue, GateRef thisValue, GateRef numArgs,
Variable* result, Label *exit, Label *slowPath, ContainersType type);
GateRef IsContainer(GateRef obj, ContainersType type)
{
switch (type) {
case ContainersType::VECTOR_FOREACH:
case ContainersType::VECTOR_REPLACEALLELEMENTS:
return IsJSAPIVector(obj);
case ContainersType::STACK_FOREACH:
return IsJSAPIStack(obj);
case ContainersType::PLAINARRAY_FOREACH:
return IsJSAPIPlainArray(obj);
case ContainersType::QUEUE_FOREACH:
return IsJSAPIQueue(obj);
case ContainersType::DEQUE_FOREACH:
return IsJSAPIDeque(obj);
default:
UNREACHABLE();
}
@ -53,7 +75,11 @@ public:
bool IsReplaceAllElements(ContainersType type)
{
switch (type) {
case ContainersType::STACK_FOREACH:
case ContainersType::VECTOR_FOREACH:
case ContainersType::PLAINARRAY_FOREACH:
case ContainersType::QUEUE_FOREACH:
case ContainersType::DEQUE_FOREACH:
return false;
case ContainersType::VECTOR_REPLACEALLELEMENTS:
return true;
@ -63,6 +89,23 @@ public:
return false;
}
bool IsPlainArray(ContainersType type)
{
switch (type) {
case ContainersType::STACK_FOREACH:
case ContainersType::VECTOR_FOREACH:
case ContainersType::VECTOR_REPLACEALLELEMENTS:
case ContainersType::QUEUE_FOREACH:
case ContainersType::DEQUE_FOREACH:
return false;
case ContainersType::PLAINARRAY_FOREACH:
return true;
default:
UNREACHABLE();
}
return false;
}
void ContainerSet(GateRef glue, GateRef obj, GateRef index, GateRef value, ContainersType type)
{
ContainersVectorStubBuilder vectorBuilder(this);
@ -77,11 +120,28 @@ public:
GateRef ContainerGetSize(GateRef obj, ContainersType type)
{
ContainersVectorStubBuilder vectorBuilder(this);
switch (type) {
case ContainersType::VECTOR_FOREACH:
case ContainersType::VECTOR_REPLACEALLELEMENTS:
case ContainersType::VECTOR_REPLACEALLELEMENTS: {
ContainersVectorStubBuilder vectorBuilder(this);
return vectorBuilder.GetSize(obj);
}
case ContainersType::STACK_FOREACH: {
ContainersStackStubBuilder stackBuilder(this);
return stackBuilder.GetSize(obj);
}
case ContainersType::PLAINARRAY_FOREACH: {
ContainersPlainArrayStubBuilder plainArrayBuilder(this);
return plainArrayBuilder.GetSize(obj);
}
case ContainersType::QUEUE_FOREACH: {
ContainersQueueStubBuilder queueBuilder(this);
return queueBuilder.GetArrayLength(obj);
}
case ContainersType::DEQUE_FOREACH: {
ContainersDequeStubBuilder dequeBuilder(this);
return dequeBuilder.GetSize(obj);
}
default:
UNREACHABLE();
}
@ -90,16 +150,50 @@ public:
GateRef ContainerGetValue(GateRef obj, GateRef index, ContainersType type)
{
ContainersVectorStubBuilder vectorBuilder(this);
switch (type) {
case ContainersType::VECTOR_FOREACH:
case ContainersType::VECTOR_REPLACEALLELEMENTS:
case ContainersType::VECTOR_REPLACEALLELEMENTS: {
ContainersVectorStubBuilder vectorBuilder(this);
return vectorBuilder.Get(obj, index);
}
case ContainersType::STACK_FOREACH: {
ContainersStackStubBuilder stackBuilder(this);
return stackBuilder.Get(obj, index);
}
case ContainersType::PLAINARRAY_FOREACH: {
ContainersPlainArrayStubBuilder plainArrayBuilder(this);
return plainArrayBuilder.Get(obj, index);
}
case ContainersType::QUEUE_FOREACH: {
ContainersQueueStubBuilder queueBuilder(this);
return queueBuilder.Get(obj, index);
}
case ContainersType::DEQUE_FOREACH: {
ContainersDequeStubBuilder dequeBuilder(this);
return dequeBuilder.Get(obj, index);
}
default:
UNREACHABLE();
}
return False();
}
GateRef PlainArrayGetKey(GateRef obj, GateRef index)
{
ContainersPlainArrayStubBuilder plainArrayBuilder(this);
return plainArrayBuilder.GetKey(obj, index);
}
GateRef QueueGetNextPosition(GateRef obj, GateRef index)
{
ContainersQueueStubBuilder queueBuilder(this);
return queueBuilder.GetNextPosition(obj, index);
}
GateRef QueueGetCurrentFront(GateRef obj)
{
ContainersQueueStubBuilder queueBuilder(this);
return queueBuilder.GetCurrentFront(obj);
}
};
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_STUB_BUILDER_H

View File

@ -1061,6 +1061,30 @@ inline GateRef StubBuilder::IsJSAPIVector(GateRef obj)
return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_API_VECTOR)));
}
inline GateRef StubBuilder::IsJSAPIStack(GateRef obj)
{
GateRef objectType = GetObjectType(LoadHClass(obj));
return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_API_STACK)));
}
inline GateRef StubBuilder::IsJSAPIPlainArray(GateRef obj)
{
GateRef objectType = GetObjectType(LoadHClass(obj));
return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_API_PLAIN_ARRAY)));
}
inline GateRef StubBuilder::IsJSAPIQueue(GateRef obj)
{
GateRef objectType = GetObjectType(LoadHClass(obj));
return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_API_QUEUE)));
}
inline GateRef StubBuilder::IsJSAPIDeque(GateRef obj)
{
GateRef objectType = GetObjectType(LoadHClass(obj));
return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_API_DEQUE)));
}
inline GateRef StubBuilder::GetTarget(GateRef proxyObj)
{
GateRef offset = IntPtr(JSProxy::TARGET_OFFSET);

View File

@ -255,6 +255,10 @@ public:
GateRef IsField(GateRef attr);
GateRef IsNonExist(GateRef attr);
GateRef IsJSAPIVector(GateRef attr);
GateRef IsJSAPIStack(GateRef obj);
GateRef IsJSAPIPlainArray(GateRef obj);
GateRef IsJSAPIQueue(GateRef obj);
GateRef IsJSAPIDeque(GateRef obj);
GateRef GetTarget(GateRef proxyObj);
GateRef HandlerBaseIsAccessor(GateRef attr);
GateRef HandlerBaseIsJSArray(GateRef attr);

View File

@ -57,7 +57,7 @@ void CommonCall::PushAsmInterpBridgeFrame(ExtendedAssembler *assembler)
void CommonCall::GetArgvAtStack(ExtendedAssembler *assembler)
{
Register r13 = __ CppJSCallAvailableRegister1();
Register r14 = __ CppJSCallAvailableRegister1();
Register r14 = __ CppJSCallAvailableRegister2();
__ Movq(Operand(rbp, FRAME_SLOT_SIZE), r13);
__ Movq(Operand(rbp, 2 * FRAME_SLOT_SIZE), r14); // 2: skip second argv
}

View File

@ -651,7 +651,8 @@ JSHandle<JSTaggedValue> ContainersPrivate::InitializePlainArray(JSThread *thread
SetFrozenFunction(thread, plainArrayFuncPrototype, "clone", ContainersPlainArray::Clone, FuncLength::ONE);
SetFrozenFunction(thread, plainArrayFuncPrototype, "has", ContainersPlainArray::Has, FuncLength::ONE);
SetFrozenFunction(thread, plainArrayFuncPrototype, "get", ContainersPlainArray::Get, FuncLength::ONE);
SetFrozenFunction(thread, plainArrayFuncPrototype, "forEach", ContainersPlainArray::ForEach, FuncLength::ONE);
SetFrozenFunction(thread, plainArrayFuncPrototype, "forEach", ContainersPlainArray::ForEach, FuncLength::ONE,
static_cast<uint8_t>(BUILTINS_STUB_ID(PlainArrayForEach)));
SetFrozenFunction(thread, plainArrayFuncPrototype, "toString", ContainersPlainArray::ToString,
FuncLength::ZERO);
SetFrozenFunction(thread, plainArrayFuncPrototype, "getIndexOfKey", ContainersPlainArray::GetIndexOfKey,
@ -729,8 +730,8 @@ JSHandle<JSTaggedValue> ContainersPrivate::InitializeStack(JSThread *thread)
// Stack.prototype.search()
SetFrozenFunction(thread, stackFuncPrototype, "locate", ContainersStack::Locate, FuncLength::ONE);
// Stack.prototype.forEach()
SetFrozenFunction(thread, stackFuncPrototype, "forEach", ContainersStack::ForEach, FuncLength::ONE);
SetFrozenFunction(thread, stackFuncPrototype, "forEach", ContainersStack::ForEach, FuncLength::ONE,
static_cast<uint8_t>(BUILTINS_STUB_ID(StackForEach)));
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
SetStringTagSymbol(thread, env, stackFuncPrototype, "Stack");
@ -861,7 +862,8 @@ JSHandle<JSTaggedValue> ContainersPrivate::InitializeQueue(JSThread *thread)
SetFrozenFunction(thread, queueFuncPrototype, "add", ContainersQueue::Add, FuncLength::ONE);
SetFrozenFunction(thread, queueFuncPrototype, "getFirst", ContainersQueue::GetFirst, FuncLength::ZERO);
SetFrozenFunction(thread, queueFuncPrototype, "pop", ContainersQueue::Pop, FuncLength::ZERO);
SetFrozenFunction(thread, queueFuncPrototype, "forEach", ContainersQueue::ForEach, FuncLength::TWO);
SetFrozenFunction(thread, queueFuncPrototype, "forEach", ContainersQueue::ForEach, FuncLength::TWO,
static_cast<uint8_t>(BUILTINS_STUB_ID(QueueForEach)));
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
SetStringTagSymbol(thread, env, queueFuncPrototype, "Queue");
@ -917,7 +919,8 @@ JSHandle<JSTaggedValue> ContainersPrivate::InitializeDeque(JSThread *thread)
SetFrozenFunction(thread, dequeFuncPrototype, "has", ContainersDeque::Has, FuncLength::ONE);
SetFrozenFunction(thread, dequeFuncPrototype, "popFirst", ContainersDeque::PopFirst, FuncLength::ZERO);
SetFrozenFunction(thread, dequeFuncPrototype, "popLast", ContainersDeque::PopLast, FuncLength::ZERO);
SetFrozenFunction(thread, dequeFuncPrototype, "forEach", ContainersDeque::ForEach, FuncLength::TWO);
SetFrozenFunction(thread, dequeFuncPrototype, "forEach", ContainersDeque::ForEach, FuncLength::TWO,
static_cast<uint8_t>(BUILTINS_STUB_ID(DequeForEach)));
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
SetStringTagSymbol(thread, env, dequeFuncPrototype, "Deque");

View File

@ -153,7 +153,7 @@ JSTaggedValue ContainersQueue::ForEach(EcmaRuntimeCallInfo *argv)
JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1);
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
uint32_t index = queue->GetCurrentFront();
uint32_t index = 0;
uint32_t k = 0;
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
while (k < len) {

View File

@ -86,6 +86,20 @@ if (globalThis["ArkPrivate"] != undefined) {
flag.push(key);
}
}
let myTest = new Queue();
for (var i = 0; i < 10; i++) {
myTest.add(i);
}
for (var i = 0; i < 5; i++) {
myTest.pop();
}
myTest.forEach(
function myFunc(item, index, arr) {
print(item);
}
);
map.forEach(elements);
if (!flag) {
print("Test Queue success!!!");

View File

@ -21,6 +21,11 @@ Test LightWeightSet success!!!
Test LinkedList success!!!
Test List success!!!
Test PlainArray success!!!
5
6
7
8
9
Test Queue success!!!
Test Stack success!!!
Test TreeMap success!!!