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/containers_arraylist_stub_builder.h" 19 #include "ecmascript/compiler/builtins/containers_deque_stub_builder.h" 20 #include "ecmascript/compiler/builtins/containers_hashmap_stub_builder.h" 21 #include "ecmascript/compiler/builtins/containers_hashset_stub_builder.h" 22 #include "ecmascript/compiler/builtins/containers_lightweightmap_stub_builder.h" 23 #include "ecmascript/compiler/builtins/containers_lightweightset_stub_builder.h" 24 #include "ecmascript/compiler/builtins/containers_linkedlist_stub_builder.h" 25 #include "ecmascript/compiler/builtins/containers_list_stub_builder.h" 26 #include "ecmascript/compiler/builtins/containers_plainarray_stub_builder.h" 27 #include "ecmascript/compiler/builtins/containers_queue_stub_builder.h" 28 #include "ecmascript/compiler/builtins/containers_stack_stub_builder.h" 29 #include "ecmascript/compiler/builtins/containers_vector_stub_builder.h" 30 #include "ecmascript/compiler/builtins/builtins_stubs.h" 31 #include "ecmascript/js_api/js_api_vector.h" 32 33 namespace panda::ecmascript::kungfu { 34 // enumerate container functions that use function call 35 enum class ContainersType : uint8_t { 36 VECTOR_FOREACH = 0, 37 VECTOR_REPLACEALLELEMENTS, 38 STACK_FOREACH, 39 PLAINARRAY_FOREACH, 40 QUEUE_FOREACH, 41 DEQUE_FOREACH, 42 LIGHTWEIGHTMAP_FOREACH, 43 LIGHTWEIGHTSET_FOREACH, 44 HASHMAP_FOREACH, 45 HASHSET_FOREACH, 46 LINKEDLIST_FOREACH, 47 LIST_FOREACH, 48 ARRAYLIST_FOREACH, 49 ARRAYLIST_REPLACEALLELEMENTS, 50 }; 51 52 class ContainersStubBuilder : public BuiltinsStubBuilder { 53 public: ContainersStubBuilder(StubBuilder * parent)54 explicit ContainersStubBuilder(StubBuilder *parent) 55 : BuiltinsStubBuilder(parent) {} 56 ~ContainersStubBuilder() override = default; 57 NO_MOVE_SEMANTIC(ContainersStubBuilder); 58 NO_COPY_SEMANTIC(ContainersStubBuilder); GenerateCircuit()59 void GenerateCircuit() override {} 60 61 void ContainersCommonFuncCall(GateRef glue, GateRef thisValue, GateRef numArgs, 62 Variable* result, Label *exit, Label *slowPath, ContainersType type); 63 64 void QueueCommonFuncCall(GateRef glue, GateRef thisValue, GateRef numArgs, 65 Variable* result, Label *exit, Label *slowPath, ContainersType type); 66 67 void DequeCommonFuncCall(GateRef glue, GateRef thisValue, GateRef numArgs, 68 Variable* result, Label *exit, Label *slowPath, ContainersType type); 69 70 void ContainersLightWeightCall(GateRef glue, GateRef thisValue, GateRef numArgs, 71 Variable* result, Label *exit, Label *slowPath, ContainersType type); 72 73 void ContainersHashCall(GateRef glue, GateRef thisValue, GateRef numArgs, 74 Variable* result, Label *exit, Label *slowPath, ContainersType type); 75 76 void ContainersLinkedListCall(GateRef glue, GateRef thisValue, GateRef numArgs, 77 Variable* result, Label *exit, Label *slowPath, ContainersType type); 78 IsContainer(GateRef obj,ContainersType type)79 GateRef IsContainer(GateRef obj, ContainersType type) 80 { 81 switch (type) { 82 case ContainersType::VECTOR_FOREACH: 83 case ContainersType::VECTOR_REPLACEALLELEMENTS: 84 return IsJSAPIVector(obj); 85 case ContainersType::STACK_FOREACH: 86 return IsJSAPIStack(obj); 87 case ContainersType::PLAINARRAY_FOREACH: 88 return IsJSAPIPlainArray(obj); 89 case ContainersType::QUEUE_FOREACH: 90 return IsJSAPIQueue(obj); 91 case ContainersType::DEQUE_FOREACH: 92 return IsJSAPIDeque(obj); 93 case ContainersType::LIGHTWEIGHTMAP_FOREACH: 94 return IsJSAPILightWeightMap(obj); 95 case ContainersType::LIGHTWEIGHTSET_FOREACH: 96 return IsJSAPILightWeightSet(obj); 97 case ContainersType::HASHMAP_FOREACH: 98 return IsJSAPIHashMap(obj); 99 case ContainersType::HASHSET_FOREACH: 100 return IsJSAPIHashSet(obj); 101 case ContainersType::LINKEDLIST_FOREACH: 102 return IsJSAPILinkedList(obj); 103 case ContainersType::LIST_FOREACH: 104 return IsJSAPIList(obj); 105 case ContainersType::ARRAYLIST_FOREACH: 106 case ContainersType::ARRAYLIST_REPLACEALLELEMENTS: 107 return IsJSAPIArrayList(obj); 108 default: 109 LOG_ECMA(FATAL) << "this branch is unreachable"; 110 UNREACHABLE(); 111 } 112 return False(); 113 } 114 IsReplaceAllElements(ContainersType type)115 bool IsReplaceAllElements(ContainersType type) 116 { 117 switch (type) { 118 case ContainersType::STACK_FOREACH: 119 case ContainersType::VECTOR_FOREACH: 120 case ContainersType::PLAINARRAY_FOREACH: 121 case ContainersType::QUEUE_FOREACH: 122 case ContainersType::DEQUE_FOREACH: 123 case ContainersType::ARRAYLIST_FOREACH: 124 return false; 125 case ContainersType::VECTOR_REPLACEALLELEMENTS: 126 case ContainersType::ARRAYLIST_REPLACEALLELEMENTS: 127 return true; 128 default: 129 LOG_ECMA(FATAL) << "this branch is unreachable"; 130 UNREACHABLE(); 131 } 132 return false; 133 } 134 IsPlainArray(ContainersType type)135 bool IsPlainArray(ContainersType type) 136 { 137 switch (type) { 138 case ContainersType::STACK_FOREACH: 139 case ContainersType::VECTOR_FOREACH: 140 case ContainersType::VECTOR_REPLACEALLELEMENTS: 141 case ContainersType::QUEUE_FOREACH: 142 case ContainersType::DEQUE_FOREACH: 143 case ContainersType::ARRAYLIST_FOREACH: 144 case ContainersType::ARRAYLIST_REPLACEALLELEMENTS: 145 return false; 146 case ContainersType::PLAINARRAY_FOREACH: 147 return true; 148 default: 149 LOG_ECMA(FATAL) << "this branch is unreachable"; 150 UNREACHABLE(); 151 } 152 return false; 153 } 154 IsArrayListReplaceAllelements(ContainersType type)155 bool IsArrayListReplaceAllelements(ContainersType type) 156 { 157 switch (type) { 158 case ContainersType::STACK_FOREACH: 159 case ContainersType::VECTOR_FOREACH: 160 case ContainersType::VECTOR_REPLACEALLELEMENTS: 161 case ContainersType::QUEUE_FOREACH: 162 case ContainersType::DEQUE_FOREACH: 163 case ContainersType::ARRAYLIST_FOREACH: 164 case ContainersType::PLAINARRAY_FOREACH: 165 return false; 166 case ContainersType::ARRAYLIST_REPLACEALLELEMENTS: 167 return true; 168 default: 169 LOG_ECMA(FATAL) << "this branch is unreachable"; 170 UNREACHABLE(); 171 } 172 return false; 173 } 174 ContainerSet(GateRef glue,GateRef obj,GateRef index,GateRef value,ContainersType type)175 void ContainerSet(GateRef glue, GateRef obj, GateRef index, GateRef value, ContainersType type) 176 { 177 switch (type) { 178 case ContainersType::VECTOR_REPLACEALLELEMENTS: { 179 ContainersVectorStubBuilder vectorBuilder(this); 180 vectorBuilder.Set(glue, obj, index, value); 181 break; 182 } 183 case ContainersType::ARRAYLIST_REPLACEALLELEMENTS: { 184 ContainersArrayListStubBuilder arrayListBuilder(this); 185 arrayListBuilder.Set(glue, obj, index, value); 186 break; 187 } 188 default: 189 LOG_ECMA(FATAL) << "this branch is unreachable"; 190 UNREACHABLE(); 191 } 192 } 193 ContainerGetSize(GateRef obj,ContainersType type)194 GateRef ContainerGetSize(GateRef obj, ContainersType type) 195 { 196 switch (type) { 197 case ContainersType::VECTOR_FOREACH: 198 case ContainersType::VECTOR_REPLACEALLELEMENTS: { 199 ContainersVectorStubBuilder vectorBuilder(this); 200 return vectorBuilder.GetSize(obj); 201 } 202 case ContainersType::STACK_FOREACH: { 203 ContainersStackStubBuilder stackBuilder(this); 204 return stackBuilder.GetSize(obj); 205 } 206 case ContainersType::PLAINARRAY_FOREACH: { 207 ContainersPlainArrayStubBuilder plainArrayBuilder(this); 208 return plainArrayBuilder.GetSize(obj); 209 } 210 case ContainersType::QUEUE_FOREACH: { 211 ContainersQueueStubBuilder queueBuilder(this); 212 return queueBuilder.GetArrayLength(obj); 213 } 214 case ContainersType::DEQUE_FOREACH: { 215 ContainersDequeStubBuilder dequeBuilder(this); 216 return dequeBuilder.GetSize(obj); 217 } 218 case ContainersType::LIGHTWEIGHTMAP_FOREACH: { 219 ContainersLightWeightMapStubBuilder lightWeightMapBuilder(this); 220 return lightWeightMapBuilder.GetSize(obj); 221 } 222 case ContainersType::LIGHTWEIGHTSET_FOREACH: { 223 ContainersLightWeightSetStubBuilder lightWeightSetBuilder(this); 224 return lightWeightSetBuilder.GetSize(obj); 225 } 226 case ContainersType::HASHMAP_FOREACH: { 227 ContainersHashMapStubBuilder hashMapBuilder(this); 228 return hashMapBuilder.GetTableLength(obj); 229 } 230 case ContainersType::HASHSET_FOREACH: { 231 ContainersHashSetStubBuilder hashSetBuilder(this); 232 return hashSetBuilder.GetTableLength(obj); 233 } 234 case ContainersType::LINKEDLIST_FOREACH: { 235 ContainersLinkedListStubBuilder linkedListBuilder(this); 236 return linkedListBuilder.GetTableLength(obj); 237 } 238 case ContainersType::LIST_FOREACH: { 239 ContainersListStubBuilder listBuilder(this); 240 return listBuilder.GetTableLength(obj); 241 } 242 case ContainersType::ARRAYLIST_REPLACEALLELEMENTS: 243 case ContainersType::ARRAYLIST_FOREACH: { 244 ContainersArrayListStubBuilder arrayListBuilder(this); 245 return arrayListBuilder.GetSize(obj); 246 } 247 default: 248 LOG_ECMA(FATAL) << "this branch is unreachable"; 249 UNREACHABLE(); 250 } 251 return False(); 252 } 253 ContainerGetValue(GateRef obj,GateRef index,ContainersType type)254 GateRef ContainerGetValue(GateRef obj, GateRef index, ContainersType type) 255 { 256 switch (type) { 257 case ContainersType::VECTOR_FOREACH: 258 case ContainersType::VECTOR_REPLACEALLELEMENTS: { 259 ContainersVectorStubBuilder vectorBuilder(this); 260 return vectorBuilder.Get(obj, index); 261 } 262 case ContainersType::STACK_FOREACH: { 263 ContainersStackStubBuilder stackBuilder(this); 264 return stackBuilder.Get(obj, index); 265 } 266 case ContainersType::PLAINARRAY_FOREACH: { 267 ContainersPlainArrayStubBuilder plainArrayBuilder(this); 268 return plainArrayBuilder.Get(obj, index); 269 } 270 case ContainersType::QUEUE_FOREACH: { 271 ContainersQueueStubBuilder queueBuilder(this); 272 return queueBuilder.Get(obj, index); 273 } 274 case ContainersType::DEQUE_FOREACH: { 275 ContainersDequeStubBuilder dequeBuilder(this); 276 return dequeBuilder.Get(obj, index); 277 } 278 case ContainersType::LIGHTWEIGHTMAP_FOREACH: { 279 ContainersLightWeightMapStubBuilder lightWeightMapBuilder(this); 280 return lightWeightMapBuilder.GetValue(obj, index); 281 } 282 case ContainersType::LIGHTWEIGHTSET_FOREACH: { 283 ContainersLightWeightSetStubBuilder lightWeightSetBuilder(this); 284 return lightWeightSetBuilder.GetValue(obj, index); 285 } 286 case ContainersType::ARRAYLIST_REPLACEALLELEMENTS: 287 case ContainersType::ARRAYLIST_FOREACH: { 288 ContainersArrayListStubBuilder arrayListBuilder(this); 289 return arrayListBuilder.Get(obj, index); 290 } 291 default: 292 LOG_ECMA(FATAL) << "this branch is unreachable"; 293 UNREACHABLE(); 294 } 295 return False(); 296 } 297 ContainerGetKey(GateRef obj,GateRef index,ContainersType type)298 GateRef ContainerGetKey(GateRef obj, GateRef index, ContainersType type) 299 { 300 switch (type) { 301 case ContainersType::LIGHTWEIGHTMAP_FOREACH: { 302 ContainersLightWeightMapStubBuilder lightWeightMapBuilder(this); 303 return lightWeightMapBuilder.GetKey(obj, index); 304 } 305 case ContainersType::LIGHTWEIGHTSET_FOREACH: { 306 ContainersLightWeightSetStubBuilder lightWeightSetBuilder(this); 307 return lightWeightSetBuilder.GetKey(obj, index); 308 } 309 default: 310 LOG_ECMA(FATAL) << "this branch is unreachable"; 311 UNREACHABLE(); 312 } 313 return False(); 314 } 315 ContainerGetNode(GateRef obj,GateRef index,ContainersType type)316 GateRef ContainerGetNode(GateRef obj, GateRef index, ContainersType type) 317 { 318 switch (type) { 319 case ContainersType::HASHMAP_FOREACH: { 320 ContainersHashMapStubBuilder hashMapBuilder(this); 321 return hashMapBuilder.GetNode(obj, index); 322 } 323 case ContainersType::HASHSET_FOREACH: { 324 ContainersHashSetStubBuilder hashSetBuilder(this); 325 return hashSetBuilder.GetNode(obj, index); 326 } 327 case ContainersType::LINKEDLIST_FOREACH: { 328 ContainersLinkedListStubBuilder linkedListBuilder(this); 329 return linkedListBuilder.GetNode(obj, index); 330 } 331 case ContainersType::LIST_FOREACH: { 332 ContainersListStubBuilder listBuilder(this); 333 return listBuilder.GetNode(obj, index); 334 } 335 default: 336 LOG_ECMA(FATAL) << "this branch is unreachable"; 337 UNREACHABLE(); 338 } 339 return False(); 340 } 341 PlainArrayGetKey(GateRef obj,GateRef index)342 GateRef PlainArrayGetKey(GateRef obj, GateRef index) 343 { 344 ContainersPlainArrayStubBuilder plainArrayBuilder(this); 345 return plainArrayBuilder.GetKey(obj, index); 346 } 347 QueueGetNextPosition(GateRef obj,GateRef index)348 GateRef QueueGetNextPosition(GateRef obj, GateRef index) 349 { 350 ContainersQueueStubBuilder queueBuilder(this); 351 return queueBuilder.GetNextPosition(obj, index); 352 } 353 QueueGetCurrentFront(GateRef obj)354 GateRef QueueGetCurrentFront(GateRef obj) 355 { 356 ContainersQueueStubBuilder queueBuilder(this); 357 return queueBuilder.GetCurrentFront(obj); 358 } 359 }; 360 } // namespace panda::ecmascript::kungfu 361 #endif // ECMASCRIPT_COMPILER_BUILTINS_CONTAINERS_STUB_BUILDER_H