• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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