1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecmascript/compiler/builtins/containers_deque_stub_builder.h"
17
18 #include "ecmascript/compiler/builtins/builtins_stubs.h"
19 #include "ecmascript/compiler/call_stub_builder.h"
20 #include "ecmascript/compiler/stub_builder-inl.h"
21
22 namespace panda::ecmascript::kungfu {
ForEach(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)23 void ContainersDequeStubBuilder::ForEach(GateRef glue, GateRef thisValue, GateRef numArgs, Variable *result,
24 Label *exit, Label *slowPath)
25 {
26 auto env = GetEnvironment();
27 DEFVARIABLE(thisObj, VariableType::JS_ANY(), thisValue);
28 DEFVARIABLE(thisArg, VariableType::JS_ANY(), Undefined());
29 DEFVARIABLE(key, VariableType::INT64(), Int64(0));
30 DEFVARIABLE(kValue, VariableType::JS_ANY(), Undefined());
31 DEFVARIABLE(length, VariableType::INT32(), Int32(0));
32 DEFVARIABLE(first, VariableType::INT32(), Int32(0));
33 DEFVARIABLE(index, VariableType::INT32(), Int32(0));
34 Label isDeque(env);
35 Label notDeque(env);
36 Label objIsJSProxy(env);
37 Label objNotJSProxy(env);
38 Label objIsJSAPIDeque(env);
39 Label thisArgUndefined(env);
40 Label thisArgNotUndefined(env);
41 Label callbackUndefined(env);
42 Label callbackNotUndefined(env);
43 Label nextCount(env);
44 Label loopHead(env);
45 Label loopEnd(env);
46 Label next(env);
47 Label afterLoop(env);
48 Label thisValueIsHeapObj(env);
49 GateRef callbackFnHandle;
50 BRANCH(TaggedIsHeapObject(thisValue), &thisValueIsHeapObj, slowPath);
51 Bind(&thisValueIsHeapObj);
52 BRANCH(IsJSAPIDeque(*thisObj), &isDeque, ¬Deque);
53 Bind(¬Deque);
54 {
55 BRANCH(IsJsProxy(*thisObj), &objIsJSProxy, &objNotJSProxy);
56 Bind(&objIsJSProxy);
57 {
58 GateRef tempObj = GetTarget(*thisObj);
59 BRANCH(IsJSAPIDeque(tempObj), &objIsJSAPIDeque, slowPath);
60 Bind(&objIsJSAPIDeque);
61 {
62 thisObj = tempObj;
63 Jump(&isDeque);
64 }
65 }
66 Bind(&objNotJSProxy);
67 Jump(slowPath);
68 }
69 Bind(&isDeque);
70 {
71 BRANCH(Int64GreaterThanOrEqual(IntPtr(0), numArgs), &callbackUndefined, &callbackNotUndefined);
72 Bind(&callbackUndefined);
73 Jump(slowPath);
74 Bind(&callbackNotUndefined);
75 {
76 Label isCall(env);
77 Label notCall(env);
78 Label isHeapObj(env);
79 callbackFnHandle = GetCallArg0(numArgs);
80 BRANCH(TaggedIsHeapObject(callbackFnHandle), &isHeapObj, slowPath);
81 Bind(&isHeapObj);
82 BRANCH(IsCallable(callbackFnHandle), &isCall, ¬Call);
83 Bind(¬Call);
84 Jump(slowPath);
85 Bind(&isCall);
86 {
87 BRANCH(Int64GreaterThanOrEqual(IntPtr(1), numArgs), &thisArgUndefined, &thisArgNotUndefined);
88 Bind(&thisArgUndefined);
89 Jump(&nextCount);
90 Bind(&thisArgNotUndefined);
91 thisArg = GetCallArg1(numArgs);
92 Jump(&nextCount);
93 }
94 }
95 }
96 Bind(&nextCount);
97 {
98 first = GetFirst(*thisObj);
99 GateRef last = GetLast(*thisObj);
100 GateRef capacity = GetElementsLength(*thisObj);
101 Jump(&loopHead);
102 LoopBegin(&loopHead);
103 {
104 Label lenChange(env);
105 Label hasException(env);
106 Label notHasException(env);
107 Label setValue(env);
108 BRANCH(Int32NotEqual(*first, last), &next, &afterLoop);
109 Bind(&next);
110 {
111 kValue = Get(*thisObj, *index);
112 key = IntToTaggedInt(*index);
113 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
114 callArgs.callThisArg3WithReturnArgs = { *thisArg, *kValue, *key, *thisObj };
115 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
116 Circuit::NullGate(), callArgs);
117 GateRef retValue = callBuilder.JSCallDispatch();
118 BRANCH(HasPendingException(glue), &hasException, ¬HasException);
119 Bind(&hasException);
120 {
121 result->WriteVariable(retValue);
122 Jump(exit);
123 }
124 Bind(¬HasException);
125 Jump(&loopEnd);
126 }
127 }
128 Bind(&loopEnd);
129 first = Int32Mod(Int32Add(*first, Int32(1)), capacity);
130 index = Int32Add(*index, Int32(1));
131 LoopEnd(&loopHead, env, glue);
132 }
133 Bind(&afterLoop);
134 Jump(exit);
135 }
136 }
137