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