1 /* 2 * Copyright (c) 2022-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 #ifndef ECMASCRIPT_JS_API_JS_API_LIGHTWEIGHTMAP_H 17 #define ECMASCRIPT_JS_API_JS_API_LIGHTWEIGHTMAP_H 18 19 #include "ecmascript/js_object.h" 20 #include "ecmascript/js_tagged_value-inl.h" 21 22 namespace panda::ecmascript { 23 enum class AccossorsKind { HASH = 0, KEY, VALUE }; 24 struct HashParams { 25 JSHandle<TaggedArray> hashArray; 26 JSHandle<TaggedArray> keyArray; 27 JSTaggedValue *key; 28 }; 29 30 // The status of the KEY in the container, including whether the KEY exists, 31 // the HASH corresponding to the KEY, and the INDEX where the KEY is located or will be inserted. 32 struct KeyState { 33 bool existed; 34 int32_t hash; 35 int32_t index; 36 }; 37 class JSAPILightWeightMap : public JSObject { 38 public: 39 static constexpr int DEFAULT_CAPACITY_LENGTH = 8; 40 static constexpr int32_t HASH_REBELLION = 0xFFFFFFFF; Cast(TaggedObject * object)41 static JSAPILightWeightMap *Cast(TaggedObject *object) 42 { 43 ASSERT(JSTaggedValue(object).IsJSAPILightWeightMap()); 44 return static_cast<JSAPILightWeightMap *>(object); 45 } 46 static void InsertValue(const JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap, 47 int32_t index, const JSHandle<JSTaggedValue> &value, AccossorsKind kind); 48 static void ReplaceValue(const JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap, 49 int32_t index, const JSHandle<JSTaggedValue> &value, AccossorsKind kind); 50 static void Set(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap, 51 const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value); 52 static JSTaggedValue Get(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap, 53 const JSHandle<JSTaggedValue> &key); 54 static JSTaggedValue HasAll(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap, 55 const JSHandle<JSAPILightWeightMap> &newLightWeightMap); 56 static JSTaggedValue HasKey(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap, 57 const JSHandle<JSTaggedValue> &key); 58 static JSTaggedValue HasValue(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap, 59 const JSHandle<JSTaggedValue> &value); 60 static int32_t GetIndexOfKey(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap, 61 const JSHandle<JSTaggedValue> &key); 62 static KeyState GetStateOfKey(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap, 63 const JSHandle<JSTaggedValue> &key); 64 static int32_t GetIndexOfValue(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap, 65 const JSHandle<JSTaggedValue> &value); 66 static JSTaggedValue GetKeyAt(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap, int32_t index); 67 static void SetAll(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap, 68 const JSHandle<JSAPILightWeightMap> &newLightWeightMap); 69 static JSTaggedValue Remove(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap, 70 const JSHandle<JSTaggedValue> &key); 71 static JSTaggedValue RemoveAt(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap, int32_t index); 72 static void Clear(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap); 73 static JSTaggedValue SetValueAt(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap, 74 int32_t index, const JSHandle<JSTaggedValue> &value); 75 static JSTaggedValue IncreaseCapacityTo(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap, 76 int32_t index); 77 static JSTaggedValue ToString(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap); 78 static JSTaggedValue GetValueAt(JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap, 79 int32_t index); 80 static JSTaggedValue GetIteratorObj(JSThread *thread, const JSHandle<JSAPILightWeightMap> &obj, IterationKind type); 81 static bool GetOwnProperty(JSThread *thread, const JSHandle<JSAPILightWeightMap> &map, 82 const JSHandle<JSTaggedValue> &key, 83 PropertyDescriptor &desc); 84 JSTaggedValue IsEmpty(); GetSize()85 inline uint32_t GetSize() const 86 { 87 return GetLength(); 88 } 89 90 static constexpr size_t LWP_HASHES_OFFSET = JSObject::SIZE; 91 ACCESSORS(Hashes, LWP_HASHES_OFFSET, LWP_KEYS_OFFSET); 92 ACCESSORS(Keys, LWP_KEYS_OFFSET, LWP_VALUES_OFFSET); 93 ACCESSORS(Values, LWP_VALUES_OFFSET, LWP_LENGTH_OFFSET); 94 ACCESSORS_PRIMITIVE_FIELD(Length, uint32_t, LWP_LENGTH_OFFSET, LAST_OFFSET); 95 DEFINE_ALIGN_SIZE(LAST_OFFSET); 96 DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject,LWP_HASHES_OFFSET,LWP_LENGTH_OFFSET)97 DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, LWP_HASHES_OFFSET, LWP_LENGTH_OFFSET) 98 DECL_DUMP() 99 100 private: 101 static inline uint32_t ComputeCapacity(uint32_t oldCapacity) 102 { 103 uint32_t newCapacity = oldCapacity + (oldCapacity >> 1U); 104 return newCapacity > DEFAULT_CAPACITY_LENGTH ? newCapacity : DEFAULT_CAPACITY_LENGTH; 105 }; 106 static JSHandle<TaggedArray> GrowCapacity(const JSThread *thread, JSHandle<TaggedArray> &oldArray, 107 uint32_t needCapacity); 108 static void SetArrayByKind(const JSThread *thread, 109 const JSHandle<JSAPILightWeightMap> &lightWeightMap, 110 const JSHandle<TaggedArray> &array, 111 AccossorsKind kind); 112 static void RemoveValue(const JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap, uint32_t index, 113 AccossorsKind kind); 114 static void SetValue(const JSThread *thread, const JSHandle<JSAPILightWeightMap> &lightWeightMap, 115 int32_t index, const JSHandle<JSTaggedValue> &value, AccossorsKind kind); 116 static int32_t Hash(JSTaggedValue key); 117 static int32_t BinarySearchHashes(JSHandle<TaggedArray> &array, int32_t hash, int32_t size); 118 static JSHandle<TaggedArray> GetArrayByKind(const JSThread *thread, 119 const JSHandle<JSAPILightWeightMap> &lightWeightMap, 120 AccossorsKind kind); 121 static int32_t AvoidHashCollision(HashParams ¶ms, int32_t index, uint32_t size, int32_t hash); 122 }; 123 } // namespace panda::ecmascript 124 125 #endif // ECMASCRIPT_JS_API_JS_API_LIGHTWEIGHTMAP_H 126