• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &notDeque);
53     Bind(&notDeque);
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, &notCall);
83             Bind(&notCall);
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, &notHasException);
119                 Bind(&hasException);
120                 {
121                     result->WriteVariable(retValue);
122                     Jump(exit);
123                 }
124                 Bind(&notHasException);
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