1 /*
2 * Copyright (c) 2023 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/builtins_collection_stub_builder.h"
17
18 #include "ecmascript/compiler/builtins/builtins_stubs.h"
19 #include "ecmascript/compiler/new_object_stub_builder.h"
20 #include "ecmascript/linked_hash_table.h"
21 #include "ecmascript/js_map.h"
22 #include "ecmascript/js_set.h"
23 #include "ecmascript/js_iterator.h"
24
25 namespace panda::ecmascript::kungfu {
26
27 template <typename CollectionType>
CheckCollectionObj(Label * thisCollectionObj,Label * slowPath)28 void BuiltinsCollectionStubBuilder<CollectionType>::CheckCollectionObj(Label *thisCollectionObj, Label *slowPath)
29 {
30 // check target obj
31 auto jsType = std::is_same_v<CollectionType, JSSet> ? JSType::JS_SET : JSType::JS_MAP;
32 GateRef isJsCollectionObj = IsJSObjectType(thisValue_, jsType);
33 Branch(isJsCollectionObj, thisCollectionObj, slowPath);
34 }
35
36 template <typename CollectionType>
Clear(Variable * result,Label * exit,Label * slowPath)37 void BuiltinsCollectionStubBuilder<CollectionType>::Clear(Variable *result, Label *exit, Label *slowPath)
38 {
39 auto env = GetEnvironment();
40 Label thisCollectionObj(env);
41 // check target obj
42 CheckCollectionObj(&thisCollectionObj, slowPath);
43
44 Bind(&thisCollectionObj);
45 GateRef linkedTable = GetLinked();
46 GateRef res = Circuit::NullGate();
47 if constexpr (std::is_same_v<CollectionType, JSMap>) {
48 LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject> linkedHashTableStubBuilder(this, glue_);
49 res = linkedHashTableStubBuilder.Clear(linkedTable);
50 } else {
51 LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject> linkedHashTableStubBuilder(this, glue_);
52 res = linkedHashTableStubBuilder.Clear(linkedTable);
53 }
54
55 Label exception(env);
56 Label noException(env);
57 Branch(TaggedIsException(res), &exception, &noException);
58 Bind(&noException);
59 SetLinked(res);
60 Jump(exit);
61 Bind(&exception);
62 *result = res;
63 Jump(exit);
64 }
65
66 template void BuiltinsCollectionStubBuilder<JSMap>::Clear(Variable *result, Label *exit, Label *slowPath);
67 template void BuiltinsCollectionStubBuilder<JSSet>::Clear(Variable *result, Label *exit, Label *slowPath);
68
69 template <typename CollectionType>
CreateIterator(Variable * result,Label * exit,Label * slowPath,GateRef kind)70 void BuiltinsCollectionStubBuilder<CollectionType>::CreateIterator(Variable *result,
71 Label *exit, Label *slowPath, GateRef kind)
72 {
73 auto env = GetEnvironment();
74 Label entry(env);
75 Label thisCollectionObj(env);
76 // check target obj
77 CheckCollectionObj(&thisCollectionObj, slowPath);
78
79 Bind(&thisCollectionObj);
80 NewObjectStubBuilder newBuilder(this);
81 newBuilder.SetGlue(glue_);
82 if constexpr (std::is_same_v<CollectionType, JSSet>) {
83 newBuilder.CreateJSCollectionIterator<JSSetIterator, CollectionType>(result, exit, thisValue_, kind);
84 } else {
85 newBuilder.CreateJSCollectionIterator<JSMapIterator, CollectionType>(result, exit, thisValue_, kind);
86 }
87 }
88
89 template <typename CollectionType>
Values(Variable * result,Label * exit,Label * slowPath)90 void BuiltinsCollectionStubBuilder<CollectionType>::Values(Variable *result, Label *exit, Label *slowPath)
91 {
92 GateRef kind = Int32(static_cast<int32_t>(IterationKind::VALUE));
93 CreateIterator(result, exit, slowPath, kind);
94 }
95
96 template void BuiltinsCollectionStubBuilder<JSMap>::Values(Variable *result, Label *exit, Label *slowPath);
97 template void BuiltinsCollectionStubBuilder<JSSet>::Values(Variable *result, Label *exit, Label *slowPath);
98
99 template <typename CollectionType>
Entries(Variable * result,Label * exit,Label * slowPath)100 void BuiltinsCollectionStubBuilder<CollectionType>::Entries(Variable *result, Label *exit, Label *slowPath)
101 {
102 GateRef kind = Int32(static_cast<int32_t>(IterationKind::KEY_AND_VALUE));
103 CreateIterator(result, exit, slowPath, kind);
104 }
105
106 template void BuiltinsCollectionStubBuilder<JSMap>::Entries(Variable *result, Label *exit, Label *slowPath);
107 template void BuiltinsCollectionStubBuilder<JSSet>::Entries(Variable *result, Label *exit, Label *slowPath);
108
109 template <typename CollectionType>
Keys(Variable * result,Label * exit,Label * slowPath)110 void BuiltinsCollectionStubBuilder<CollectionType>::Keys(Variable *result, Label *exit, Label *slowPath)
111 {
112 GateRef kind = Int32(static_cast<int32_t>(IterationKind::KEY));
113 CreateIterator(result, exit, slowPath, kind);
114 }
115
116 template void BuiltinsCollectionStubBuilder<JSMap>::Keys(Variable *result, Label *exit, Label *slowPath);
117
118 template <typename CollectionType>
ForEach(Variable * result,Label * exit,Label * slowPath)119 void BuiltinsCollectionStubBuilder<CollectionType>::ForEach(Variable *result, Label *exit, Label *slowPath)
120 {
121 auto env = GetEnvironment();
122 Label thisCollectionObj(env);
123 // check target obj
124 CheckCollectionObj(&thisCollectionObj, slowPath);
125
126 Bind(&thisCollectionObj);
127 GateRef callbackFnHandle = GetCallArg0(numArgs_);
128 Label callable(env);
129 // check heap obj
130 Label heapObj(env);
131 Branch(TaggedIsHeapObject(callbackFnHandle), &heapObj, slowPath);
132 Bind(&heapObj);
133 Branch(IsCallable(callbackFnHandle), &callable, slowPath);
134 Bind(&callable);
135
136 GateRef linkedTable = GetLinked();
137 GateRef res = Circuit::NullGate();
138 if constexpr (std::is_same_v<CollectionType, JSMap>) {
139 LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject> linkedHashTableStubBuilder(this, glue_);
140 res = linkedHashTableStubBuilder.ForEach(thisValue_, linkedTable, numArgs_);
141 } else {
142 LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject> linkedHashTableStubBuilder(this, glue_);
143 res = linkedHashTableStubBuilder.ForEach(thisValue_, linkedTable, numArgs_);
144 }
145
146 Label exception(env);
147 Branch(TaggedIsException(res), &exception, exit);
148 Bind(&exception);
149 *result = res;
150 Jump(exit);
151 }
152
153 template void BuiltinsCollectionStubBuilder<JSMap>::ForEach(Variable *result, Label *exit, Label *slowPath);
154 template void BuiltinsCollectionStubBuilder<JSSet>::ForEach(Variable *result, Label *exit, Label *slowPath);
155
156 template <typename CollectionType>
MapSetOrSetAdd(Variable * result,Label * exit,Label * slowPath,bool isJsMapSet)157 void BuiltinsCollectionStubBuilder<CollectionType>::MapSetOrSetAdd(
158 Variable *result, Label *exit, Label *slowPath, bool isJsMapSet)
159 {
160 auto env = GetEnvironment();
161 Label thisCollectionObj(env);
162 // check target obj
163 CheckCollectionObj(&thisCollectionObj, slowPath);
164 Bind(&thisCollectionObj);
165 GateRef key = GetCallArg0(numArgs_);
166 // check key
167 Label keyNotHole(env);
168 Branch(TaggedIsHole(key), slowPath, &keyNotHole);
169 Bind(&keyNotHole);
170 GateRef value = isJsMapSet ? GetCallArg1(numArgs_) : key;
171 GateRef linkedTable = GetLinked();
172 GateRef res = Circuit::NullGate();
173 if constexpr (std::is_same_v<CollectionType, JSMap>) {
174 LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject> linkedHashTableStubBuilder(this, glue_);
175 res = linkedHashTableStubBuilder.Insert(linkedTable, key, value);
176 } else {
177 LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject> linkedHashTableStubBuilder(this, glue_);
178 res = linkedHashTableStubBuilder.Insert(linkedTable, key, value);
179 }
180
181 SetLinked(res);
182 *result = thisValue_;
183 Jump(exit);
184 }
185
186 template <typename CollectionType>
Set(Variable * result,Label * exit,Label * slowPath)187 void BuiltinsCollectionStubBuilder<CollectionType>::Set(Variable *result, Label *exit, Label *slowPath)
188 {
189 MapSetOrSetAdd(result, exit, slowPath, true);
190 }
191
192 template void BuiltinsCollectionStubBuilder<JSMap>::Set(Variable *result, Label *exit, Label *slowPath);
193
194 template <typename CollectionType>
Add(Variable * result,Label * exit,Label * slowPath)195 void BuiltinsCollectionStubBuilder<CollectionType>::Add(Variable *result, Label *exit, Label *slowPath)
196 {
197 MapSetOrSetAdd(result, exit, slowPath, false);
198 }
199
200 template void BuiltinsCollectionStubBuilder<JSSet>::Add(Variable *result, Label *exit, Label *slowPath);
201
202 template <typename CollectionType>
Delete(Variable * result,Label * exit,Label * slowPath)203 void BuiltinsCollectionStubBuilder<CollectionType>::Delete(Variable *result, Label *exit, Label *slowPath)
204 {
205 auto env = GetEnvironment();
206 Label thisCollectionObj(env);
207 // check target obj
208 CheckCollectionObj(&thisCollectionObj, slowPath);
209
210 Bind(&thisCollectionObj);
211 GateRef key = GetCallArg0(numArgs_);
212 GateRef linkedTable = GetLinked();
213 GateRef res = Circuit::NullGate();
214 if constexpr (std::is_same_v<CollectionType, JSMap>) {
215 LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject> linkedHashTableStubBuilder(this, glue_);
216 res = linkedHashTableStubBuilder.Delete(linkedTable, key);
217 } else {
218 LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject> linkedHashTableStubBuilder(this, glue_);
219 res = linkedHashTableStubBuilder.Delete(linkedTable, key);
220 }
221 *result = res;
222 Jump(exit);
223 }
224
225 template void BuiltinsCollectionStubBuilder<JSMap>::Delete(Variable *result, Label *exit, Label *slowPath);
226 template void BuiltinsCollectionStubBuilder<JSSet>::Delete(Variable *result, Label *exit, Label *slowPath);
227
228 template <typename CollectionType>
Has(Variable * result,Label * exit,Label * slowPath)229 void BuiltinsCollectionStubBuilder<CollectionType>::Has(Variable *result, Label *exit, Label *slowPath)
230 {
231 auto env = GetEnvironment();
232 Label thisCollectionObj(env);
233 // check target obj
234 CheckCollectionObj(&thisCollectionObj, slowPath);
235
236 Bind(&thisCollectionObj);
237 GateRef key = GetCallArg0(numArgs_);
238 GateRef linkedTable = GetLinked();
239 GateRef res = Circuit::NullGate();
240 if constexpr (std::is_same_v<CollectionType, JSMap>) {
241 LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject> linkedHashTableStubBuilder(this, glue_);
242 res = linkedHashTableStubBuilder.Has(linkedTable, key);
243 } else {
244 LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject> linkedHashTableStubBuilder(this, glue_);
245 res = linkedHashTableStubBuilder.Has(linkedTable, key);
246 }
247 *result = res;
248 Jump(exit);
249 }
250
251 template void BuiltinsCollectionStubBuilder<JSMap>::Has(Variable *result, Label *exit, Label *slowPath);
252 template void BuiltinsCollectionStubBuilder<JSSet>::Has(Variable *result, Label *exit, Label *slowPath);
253 } // namespace panda::ecmascript::kungfu
254