• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #ifndef ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_STUB_BUILDER_H
17 #define ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_STUB_BUILDER_H
18 #include "ecmascript/compiler/builtins/builtins_stubs.h"
19 #include "ecmascript/compiler/stub_builder-inl.h"
20 #include "ecmascript/js_api/js_api_arraylist.h"
21 #include "ecmascript/js_api/js_api_hashmap.h"
22 #include "ecmascript/js_api/js_api_hashset.h"
23 #include "ecmascript/js_api/js_api_lightweightmap.h"
24 #include "ecmascript/js_api/js_api_lightweightset.h"
25 #include "ecmascript/js_api/js_api_linked_list.h"
26 #include "ecmascript/js_api/js_api_list.h"
27 #include "ecmascript/js_api/js_api_plain_array.h"
28 #include "ecmascript/js_api/js_api_stack.h"
29 #include "ecmascript/js_api/js_api_vector.h"
30 
31 namespace panda::ecmascript::kungfu {
32 // enumerate container functions that use function call
33 enum class ContainersType : uint8_t {
34     VECTOR_FOREACH = 0,
35     VECTOR_REPLACEALLELEMENTS,
36     STACK_FOREACH,
37     PLAINARRAY_FOREACH,
38     QUEUE_FOREACH,
39     DEQUE_FOREACH,
40     LIGHTWEIGHTMAP_FOREACH,
41     LIGHTWEIGHTSET_FOREACH,
42     HASHMAP_FOREACH,
43     HASHSET_FOREACH,
44     LINKEDLIST_FOREACH,
45     LIST_FOREACH,
46     ARRAYLIST_FOREACH,
47     ARRAYLIST_REPLACEALLELEMENTS,
48 };
49 
50 class ContainersCommonStubBuilder : public BuiltinsStubBuilder {
51 public:
ContainersCommonStubBuilder(StubBuilder * parent)52     explicit ContainersCommonStubBuilder(StubBuilder *parent)
53         : BuiltinsStubBuilder(parent) {}
54     ~ContainersCommonStubBuilder() override = default;
55     NO_MOVE_SEMANTIC(ContainersCommonStubBuilder);
56     NO_COPY_SEMANTIC(ContainersCommonStubBuilder);
GenerateCircuit()57     void GenerateCircuit() override {}
58 
59     void ContainersCommonFuncCall(GateRef glue, GateRef thisValue, GateRef numArgs,
60         Variable* result, Label *exit, Label *slowPath, ContainersType type);
61 
62     void ContainersLightWeightCall(GateRef glue, GateRef thisValue, GateRef numArgs,
63         Variable* result, Label *exit, Label *slowPath, ContainersType type);
64 
65     void ContainersHashCall(GateRef glue, GateRef thisValue, GateRef numArgs,
66         Variable* result, Label *exit, Label *slowPath, ContainersType type);
67 
68     void ContainersLinkedListCall(GateRef glue, GateRef thisValue, GateRef numArgs,
69         Variable* result, Label *exit, Label *slowPath, ContainersType type);
70 
IsContainer(GateRef obj,ContainersType type)71     GateRef IsContainer(GateRef obj, ContainersType type)
72     {
73         switch (type) {
74             case ContainersType::VECTOR_FOREACH:
75             case ContainersType::VECTOR_REPLACEALLELEMENTS:
76                 return IsJSAPIVector(obj);
77             case ContainersType::STACK_FOREACH:
78                 return IsJSAPIStack(obj);
79             case ContainersType::PLAINARRAY_FOREACH:
80                 return IsJSAPIPlainArray(obj);
81             case ContainersType::QUEUE_FOREACH:
82                 return IsJSAPIQueue(obj);
83             case ContainersType::DEQUE_FOREACH:
84                 return IsJSAPIDeque(obj);
85             case ContainersType::LIGHTWEIGHTMAP_FOREACH:
86                 return IsJSAPILightWeightMap(obj);
87             case ContainersType::LIGHTWEIGHTSET_FOREACH:
88                 return IsJSAPILightWeightSet(obj);
89             case ContainersType::HASHMAP_FOREACH:
90                 return IsJSAPIHashMap(obj);
91             case ContainersType::HASHSET_FOREACH:
92                 return IsJSAPIHashSet(obj);
93             case ContainersType::LINKEDLIST_FOREACH:
94                 return IsJSAPILinkedList(obj);
95             case ContainersType::LIST_FOREACH:
96                 return IsJSAPIList(obj);
97             case ContainersType::ARRAYLIST_FOREACH:
98             case ContainersType::ARRAYLIST_REPLACEALLELEMENTS:
99                 return IsJSAPIArrayList(obj);
100             default:
101                 LOG_ECMA(FATAL) << "this branch is unreachable";
102                 UNREACHABLE();
103         }
104         return False();
105     }
106 
IsReplaceAllElements(ContainersType type)107     bool IsReplaceAllElements(ContainersType type)
108     {
109         switch (type) {
110             case ContainersType::STACK_FOREACH:
111             case ContainersType::VECTOR_FOREACH:
112             case ContainersType::PLAINARRAY_FOREACH:
113             case ContainersType::QUEUE_FOREACH:
114             case ContainersType::DEQUE_FOREACH:
115             case ContainersType::ARRAYLIST_FOREACH:
116                 return false;
117             case ContainersType::VECTOR_REPLACEALLELEMENTS:
118             case ContainersType::ARRAYLIST_REPLACEALLELEMENTS:
119                 return true;
120             default:
121                 LOG_ECMA(FATAL) << "this branch is unreachable";
122                 UNREACHABLE();
123         }
124         return false;
125     }
126 
IsPlainArray(ContainersType type)127     bool IsPlainArray(ContainersType type)
128     {
129         switch (type) {
130             case ContainersType::STACK_FOREACH:
131             case ContainersType::VECTOR_FOREACH:
132             case ContainersType::VECTOR_REPLACEALLELEMENTS:
133             case ContainersType::QUEUE_FOREACH:
134             case ContainersType::DEQUE_FOREACH:
135             case ContainersType::ARRAYLIST_FOREACH:
136             case ContainersType::ARRAYLIST_REPLACEALLELEMENTS:
137                 return false;
138             case ContainersType::PLAINARRAY_FOREACH:
139                 return true;
140             default:
141                 LOG_ECMA(FATAL) << "this branch is unreachable";
142                 UNREACHABLE();
143         }
144         return false;
145     }
146 
IsArrayListReplaceAllelements(ContainersType type)147     bool IsArrayListReplaceAllelements(ContainersType type)
148     {
149         switch (type) {
150             case ContainersType::STACK_FOREACH:
151             case ContainersType::VECTOR_FOREACH:
152             case ContainersType::VECTOR_REPLACEALLELEMENTS:
153             case ContainersType::QUEUE_FOREACH:
154             case ContainersType::DEQUE_FOREACH:
155             case ContainersType::ARRAYLIST_FOREACH:
156             case ContainersType::PLAINARRAY_FOREACH:
157                 return false;
158             case ContainersType::ARRAYLIST_REPLACEALLELEMENTS:
159                 return true;
160             default:
161                 LOG_ECMA(FATAL) << "this branch is unreachable";
162                 UNREACHABLE();
163         }
164         return false;
165     }
166 
ContainerGetSize(GateRef obj,ContainersType type)167     GateRef ContainerGetSize(GateRef obj, ContainersType type)
168     {
169         switch (type) {
170             case ContainersType::VECTOR_FOREACH:
171             case ContainersType::VECTOR_REPLACEALLELEMENTS: {
172                 return Load(VariableType::INT32(), obj, IntPtr(JSAPIVector::ELEMENT_COUNT_OFFSET));
173             }
174             case ContainersType::STACK_FOREACH: {
175                 GateRef top = Load(VariableType::INT32(), obj, IntPtr(JSAPIStack::TOP_OFFSET));
176                 return Int32Add(top, Int32(1));
177             }
178             case ContainersType::PLAINARRAY_FOREACH: {
179                 return Load(VariableType::INT32(), obj, IntPtr(JSAPIPlainArray::LENGTH_OFFSET));
180             }
181             case ContainersType::ARRAYLIST_REPLACEALLELEMENTS:
182             case ContainersType::ARRAYLIST_FOREACH: {
183                 GateRef len = Load(VariableType::JS_ANY(), obj, IntPtr(JSAPIArrayList::LENGTH_OFFSET));
184                 return TaggedGetInt(len);
185             }
186             case ContainersType::LIGHTWEIGHTSET_FOREACH: {
187                 return Load(VariableType::INT32(), obj, IntPtr(JSAPILightWeightSet::LENGTH_OFFSET));
188             }
189             case ContainersType::LIGHTWEIGHTMAP_FOREACH: {
190                 return Load(VariableType::INT32(), obj, IntPtr(JSAPILightWeightMap::LWP_LENGTH_OFFSET));
191             }
192             case ContainersType::HASHMAP_FOREACH: {
193                 GateRef tableOffset = IntPtr(JSAPIHashMap::HASHMAP_TABLE_INDEX);
194                 GateRef table = Load(VariableType::JS_POINTER(), obj, tableOffset);
195                 return GetLengthOfTaggedArray(table);
196             }
197             case ContainersType::HASHSET_FOREACH: {
198                 GateRef tableOffset = IntPtr(JSAPIHashSet::HASHSET_TABLE_INDEX);
199                 GateRef table = Load(VariableType::JS_POINTER(), obj, tableOffset);
200                 return GetLengthOfTaggedArray(table);
201             }
202             case ContainersType::LINKEDLIST_FOREACH: {
203                 GateRef tableOffset = IntPtr(JSAPILinkedList::DOUBLE_LIST_OFFSET);
204                 GateRef table = Load(VariableType::JS_POINTER(), obj, tableOffset);
205                 GateRef value = GetValueFromTaggedArray(table, Int32(TaggedDoubleList::NUMBER_OF_NODE_INDEX));
206                 return TaggedGetInt(value);
207             }
208             case ContainersType::LIST_FOREACH: {
209                 GateRef tableOffset = IntPtr(JSAPIList::SINGLY_LIST_OFFSET);
210                 GateRef table = Load(VariableType::JS_POINTER(), obj, tableOffset);
211                 GateRef value = GetValueFromTaggedArray(table, Int32(TaggedSingleList::NUMBER_OF_NODE_INDEX));
212                 return TaggedGetInt(value);
213             }
214             default:
215                 LOG_ECMA(FATAL) << "this branch is unreachable";
216                 UNREACHABLE();
217         }
218         return False();
219     }
220 
ContainerGetValue(GateRef obj,GateRef index,ContainersType type)221     GateRef ContainerGetValue(GateRef obj, GateRef index, ContainersType type)
222     {
223         switch (type) {
224             case ContainersType::VECTOR_FOREACH:
225             case ContainersType::VECTOR_REPLACEALLELEMENTS: {
226                 GateRef elementsOffset = IntPtr(JSObject::ELEMENTS_OFFSET);
227                 GateRef elements = Load(VariableType::JS_POINTER(), obj, elementsOffset);
228                 return GetValueFromTaggedArray(elements, index);
229             }
230             case ContainersType::STACK_FOREACH: {
231                 GateRef elementsOffset = IntPtr(JSObject::ELEMENTS_OFFSET);
232                 GateRef elements = Load(VariableType::JS_POINTER(), obj, elementsOffset);
233                 return GetValueFromTaggedArray(elements, index);
234             }
235             case ContainersType::PLAINARRAY_FOREACH: {
236                 GateRef elementsOffset = IntPtr(JSAPIPlainArray::VALUES_OFFSET);
237                 GateRef elements = Load(VariableType::JS_POINTER(), obj, elementsOffset);
238                 return GetValueFromTaggedArray(elements, index);
239             }
240             case ContainersType::ARRAYLIST_REPLACEALLELEMENTS:
241             case ContainersType::ARRAYLIST_FOREACH: {
242                 GateRef elementsOffset = IntPtr(JSObject::ELEMENTS_OFFSET);
243                 GateRef elements = Load(VariableType::JS_POINTER(), obj, elementsOffset);
244                 return GetValueFromTaggedArray(elements, index);
245             }
246             case ContainersType::LIGHTWEIGHTSET_FOREACH: {
247                 GateRef valuesOffset = IntPtr(JSAPILightWeightSet::VALUES_OFFSET);
248                 GateRef values = Load(VariableType::JS_POINTER(), obj, valuesOffset);
249                 return GetValueFromTaggedArray(values, index);
250             }
251             case ContainersType::LIGHTWEIGHTMAP_FOREACH: {
252                 GateRef valuesOffset = IntPtr(JSAPILightWeightMap::LWP_VALUES_OFFSET);
253                 GateRef values = Load(VariableType::JS_POINTER(), obj, valuesOffset);
254                 return GetValueFromTaggedArray(values, index);
255             }
256             default:
257                 LOG_ECMA(FATAL) << "this branch is unreachable";
258                 UNREACHABLE();
259         }
260         return False();
261     }
262 
ContainerGetKey(GateRef obj,GateRef index,ContainersType type)263     GateRef ContainerGetKey(GateRef obj, GateRef index, ContainersType type)
264     {
265         switch (type) {
266             case ContainersType::LIGHTWEIGHTMAP_FOREACH: {
267                 GateRef keysOffset = IntPtr(JSAPILightWeightMap::LWP_KEYS_OFFSET);
268                 GateRef keys = Load(VariableType::JS_POINTER(), obj, keysOffset);
269                 return GetValueFromTaggedArray(keys, index);
270             }
271             case ContainersType::LIGHTWEIGHTSET_FOREACH: {
272                 GateRef valuesOffset = IntPtr(JSAPILightWeightSet::VALUES_OFFSET);
273                 GateRef values = Load(VariableType::JS_POINTER(), obj, valuesOffset);
274                 return GetValueFromTaggedArray(values, index);
275             }
276             default:
277                 LOG_ECMA(FATAL) << "this branch is unreachable";
278                 UNREACHABLE();
279         }
280         return False();
281     }
282 
ContainerGetNode(GateRef obj,GateRef index,ContainersType type)283     GateRef ContainerGetNode(GateRef obj, GateRef index, ContainersType type)
284     {
285         switch (type) {
286             case ContainersType::HASHMAP_FOREACH: {
287                 GateRef tableOffset = IntPtr(JSAPIHashMap::HASHMAP_TABLE_INDEX);
288                 GateRef table = Load(VariableType::JS_POINTER(), obj, tableOffset);
289                 return GetValueFromTaggedArray(table, index);
290             }
291             case ContainersType::HASHSET_FOREACH: {
292                 GateRef tableOffset = IntPtr(JSAPIHashSet::HASHSET_TABLE_INDEX);
293                 GateRef table = Load(VariableType::JS_POINTER(), obj, tableOffset);
294                 return GetValueFromTaggedArray(table, index);
295             }
296             case ContainersType::LINKEDLIST_FOREACH: {
297                 GateRef tableOffset = IntPtr(JSAPILinkedList::DOUBLE_LIST_OFFSET);
298                 GateRef table = Load(VariableType::JS_POINTER(), obj, tableOffset);
299                 return GetValueFromTaggedArray(table, index);
300             }
301             case ContainersType::LIST_FOREACH: {
302                 GateRef tableOffset = IntPtr(JSAPIList::SINGLY_LIST_OFFSET);
303                 GateRef table = Load(VariableType::JS_POINTER(), obj, tableOffset);
304                 return GetValueFromTaggedArray(table, index);
305             }
306             default:
307                 LOG_ECMA(FATAL) << "this branch is unreachable";
308                 UNREACHABLE();
309         }
310         return False();
311     }
312 
PlainArrayGetKey(GateRef obj,GateRef index)313     GateRef PlainArrayGetKey(GateRef obj, GateRef index)
314     {
315         GateRef elementsOffset = IntPtr(JSAPIPlainArray::KEYS_OFFSET);
316         GateRef elements = Load(VariableType::JS_POINTER(), obj, elementsOffset);
317         return GetValueFromTaggedArray(elements, index);
318     }
319 };
320 }  // namespace panda::ecmascript::kungfu
321 #endif  // ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_STUB_BUILDER_H
322