1 /* 2 * Copyright (c) 2021 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_TS_TYPES_TS_OBJ_LAYOUT_INFO_H 17 #define ECMASCRIPT_TS_TYPES_TS_OBJ_LAYOUT_INFO_H 18 19 #include "ecmascript/tagged_array-inl.h" 20 21 namespace panda::ecmascript { 22 /* 23 * The TSObjLayoutInfo is organized as follows: 24 * The first position is used to store the number of properties. 25 * Store the key, gt and attribute of properties alternately starting from the second position. 26 * +---+-------+------+--------+-------+------+--------+-----+-------+------+--------+ 27 * | N | key_1 | gt_1 | attr_1 | key_2 | gt_2 | attr_2 | ... | key_N | gt_N | attr_N | 28 * +---+-------+------+--------+-----=-+------+--------+-----+-------+------+--------+ 29 */ 30 class TSObjLayoutInfo : private TaggedArray { 31 public: 32 static constexpr int MIN_PROPERTIES_LENGTH = JSObject::MIN_PROPERTIES_LENGTH; 33 static constexpr int MAX_PROPERTIES_LENGTH = PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES; 34 static constexpr int ELEMENTS_COUNT_INDEX = 0; 35 static constexpr int ELEMENTS_START_INDEX = 1; 36 static constexpr int ENTRY_SIZE = 3; 37 static constexpr int ENTRY_KEY_OFFSET = 0; 38 static constexpr int ENTRY_TYPE_OFFSET = 1; 39 static constexpr int ENTRY_ATTRIBUTE_OFFSET = 2; 40 static constexpr int DEFAULT_CAPACITY = 1; 41 static constexpr int INCREASE_CAPACITY_RATE = 1; 42 static constexpr int INVALID_INDEX = -1; 43 Cast(TaggedObject * obj)44 inline static TSObjLayoutInfo *Cast(TaggedObject *obj) 45 { 46 ASSERT(JSTaggedValue(obj).IsTaggedArray()); 47 return reinterpret_cast<TSObjLayoutInfo*>(obj); 48 } 49 GetPropertiesCapacity()50 inline uint32_t GetPropertiesCapacity() const 51 { 52 ASSERT(GetLength() >= ELEMENTS_START_INDEX); 53 ASSERT((GetLength() - ELEMENTS_START_INDEX) % ENTRY_SIZE == 0); 54 return static_cast<uint32_t>((GetLength() - ELEMENTS_START_INDEX) / ENTRY_SIZE); 55 } 56 SetNumOfProperties(const JSThread * thread,const uint32_t propertiesNum)57 inline void SetNumOfProperties(const JSThread *thread, const uint32_t propertiesNum) 58 { 59 return TaggedArray::Set(thread, ELEMENTS_COUNT_INDEX, JSTaggedValue(propertiesNum)); 60 } 61 GetNumOfProperties()62 inline uint32_t GetNumOfProperties() const 63 { 64 return TaggedArray::Get(ELEMENTS_COUNT_INDEX).GetInt(); 65 } 66 67 void AddProperty(const JSThread *thread, const JSTaggedValue key, 68 const JSTaggedValue typeIdVal, const uint32_t attr = 0); 69 70 void AddProperty(const JSThread *thread, const JSTaggedValue key, 71 const JSTaggedValue typeIdVal, const JSTaggedValue attr); 72 73 static JSHandle<TSObjLayoutInfo> PushBack(const JSThread *thread, 74 const JSHandle<TSObjLayoutInfo> &oldLayout, 75 const JSHandle<JSTaggedValue> &key, 76 const JSHandle<JSTaggedValue> &value); 77 IsValidIndex(int index)78 static inline bool IsValidIndex(int index) 79 { 80 return index != INVALID_INDEX; 81 } 82 GetLength()83 inline uint32_t GetLength() const 84 { 85 return TaggedArray::GetLength(); 86 } 87 ComputeGrowCapacity(const uint32_t oldCapacity)88 static inline uint32_t ComputeGrowCapacity(const uint32_t oldCapacity) 89 { 90 uint64_t newCapacity = (static_cast<uint64_t>(oldCapacity) << INCREASE_CAPACITY_RATE); 91 ASSERT(newCapacity <= static_cast<uint64_t>(MAX_PROPERTIES_LENGTH)); 92 if (newCapacity > static_cast<uint64_t>(MAX_PROPERTIES_LENGTH)) { 93 return MAX_PROPERTIES_LENGTH; 94 } 95 return static_cast<uint32_t>(newCapacity); 96 } 97 ComputeArrayLength(const uint32_t numOfProperties)98 static inline uint32_t ComputeArrayLength(const uint32_t numOfProperties) 99 { 100 return (numOfProperties * ENTRY_SIZE) + ELEMENTS_START_INDEX; 101 } 102 103 bool Find(JSTaggedValue key) const; 104 105 int GetElementIndexByKey(JSTaggedValue key) const; 106 107 JSTaggedValue TryGetTypeByIndexSign(const uint32_t typeId); 108 109 #define TSOBJLAYOUT_ACCESSOR_LIST(V) \ 110 V(Key, ENTRY_KEY_OFFSET) \ 111 V(TypeId, ENTRY_TYPE_OFFSET) \ 112 V(Attribute, ENTRY_ATTRIBUTE_OFFSET) 113 114 #define TSOBJLAYOUT_ACCESSOR(NAME, OFFSET) \ 115 inline void Set##NAME(const JSThread *thread, const int index, const JSTaggedValue key) \ 116 { \ 117 uint32_t idxInArray = Get##NAME##Index(index); \ 118 TaggedArray::Set(thread, idxInArray, key); \ 119 } \ 120 \ 121 inline JSTaggedValue Get##NAME(const int index) const \ 122 { \ 123 uint32_t idxInArray = Get##NAME##Index(index); \ 124 return TaggedArray::Get(idxInArray); \ 125 } \ 126 \ 127 inline uint32_t Get##NAME##Index(const int index) const \ 128 { \ 129 return ELEMENTS_START_INDEX + (static_cast<uint32_t>(index) * ENTRY_SIZE) + (OFFSET); \ 130 } 131 132 TSOBJLAYOUT_ACCESSOR_LIST(TSOBJLAYOUT_ACCESSOR) 133 #undef TSOBJLAYOUT_ACCESSOR 134 135 private: 136 static JSHandle<TSObjLayoutInfo> ExtendTSObjLayoutInfo(const JSThread *thread, 137 const JSHandle<TSObjLayoutInfo> &old, 138 JSTaggedValue initVal = JSTaggedValue::Hole()); 139 }; 140 } // namespace panda::ecmascript 141 #endif // ECMASCRIPT_TS_TYPES_TS_OBJ_LAYOUT_INFO_H 142