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_queue_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 ContainersQueueStubBuilder::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(k, VariableType::INT32(), Int32(0));
33 DEFVARIABLE(index, VariableType::INT32(), Int32(0));
34 Label valueIsJSAPIQueue(env);
35 Label valueNotJSAPIQueue(env);
36 Label objIsJSProxy(env);
37 Label objNotJSProxy(env);
38 Label objIsJSAPIQueue(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(IsJSAPIQueue(glue, *thisObj), &valueIsJSAPIQueue, &valueNotJSAPIQueue);
53 Bind(&valueNotJSAPIQueue);
54 {
55 BRANCH(IsJsProxy(glue, *thisObj), &objIsJSProxy, &objNotJSProxy);
56 Bind(&objIsJSProxy);
57 {
58 GateRef tempObj = GetTarget(glue, *thisObj);
59 BRANCH(IsJSAPIQueue(glue, tempObj), &objIsJSAPIQueue, slowPath);
60 Bind(&objIsJSAPIQueue);
61 {
62 thisObj = tempObj;
63 Jump(&valueIsJSAPIQueue);
64 }
65 }
66 Bind(&objNotJSProxy);
67 Jump(slowPath);
68 }
69 Bind(&valueIsJSAPIQueue);
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(glue, 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 length = GetArrayLength(glue, *thisObj);
99 Jump(&loopHead);
100 LoopBegin(&loopHead);
101 {
102 Label lenChange(env);
103 Label hasException(env);
104 Label notHasException(env);
105 Label setValue(env);
106 BRANCH(Int32LessThan(*k, *length), &next, &afterLoop);
107 Bind(&next);
108 {
109 kValue = Get(glue, *thisObj, *index);
110 index = GetNextPosition(glue, *thisObj, *index);
111 key = IntToTaggedInt(*k);
112 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
113 callArgs.callThisArg3WithReturnArgs = { *thisArg, *kValue, *key, *thisObj };
114 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
115 Circuit::NullGate(), callArgs);
116 GateRef retValue = callBuilder.JSCallDispatch();
117 BRANCH(HasPendingException(glue), &hasException, ¬HasException);
118 Bind(&hasException);
119 {
120 result->WriteVariable(retValue);
121 Jump(exit);
122 }
123 Bind(¬HasException);
124 Jump(&loopEnd);
125 }
126 }
127 Bind(&loopEnd);
128 k = Int32Add(*k, Int32(1));
129 LoopEndWithCheckSafePoint(&loopHead, env, glue);
130 }
131 Bind(&afterLoop);
132 Jump(exit);
133 }
134 }
135