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_TAGGED_ARRAY_H 17 #define ECMASCRIPT_TAGGED_ARRAY_H 18 19 #include "ecmascript/base/number_helper.h" 20 #include "ecmascript/js_hclass.h" 21 #include "ecmascript/js_tagged_value.h" 22 23 namespace panda::ecmascript { 24 class ObjectFactory; 25 class JSThread; 26 27 class TaggedArray : public TaggedObject { 28 public: 29 static constexpr uint32_t MAX_ARRAY_INDEX = std::numeric_limits<uint32_t>::max(); 30 static constexpr uint32_t MAX_END_UNUSED = 4; 31 32 CAST_CHECK(TaggedArray, IsTaggedArray); 33 34 JSTaggedValue Get(uint32_t idx) const; 35 36 uint32_t GetIdx(const JSTaggedValue &value) const; 37 38 template<typename T> 39 void Set(const JSThread *thread, uint32_t idx, const JSHandle<T> &value); 40 41 JSTaggedValue Get(const JSThread *thread, uint32_t idx) const; 42 43 template <bool needBarrier = true> 44 void Set(const JSThread *thread, uint32_t idx, const JSTaggedValue &value); 45 46 static inline JSHandle<TaggedArray> Append(const JSThread *thread, const JSHandle<TaggedArray> &first, 47 const JSHandle<TaggedArray> &second); 48 static inline JSHandle<TaggedArray> AppendSkipHole(const JSThread *thread, const JSHandle<TaggedArray> &first, 49 const JSHandle<TaggedArray> &second, uint32_t copyLength); 50 ComputeSize(size_t elemSize,uint32_t length)51 static inline size_t ComputeSize(size_t elemSize, uint32_t length) 52 { 53 ASSERT(elemSize != 0); 54 size_t size = DATA_OFFSET + elemSize * length; 55 return size; 56 } 57 GetData()58 inline JSTaggedType *GetData() const 59 { 60 return reinterpret_cast<JSTaggedType *>(ToUintPtr(this) + DATA_OFFSET); 61 } 62 63 inline bool IsDictionaryMode() const; 64 65 bool HasDuplicateEntry() const; 66 67 static JSHandle<TaggedArray> SetCapacity(const JSThread *thread, const JSHandle<TaggedArray> &array, 68 uint32_t capa); 69 70 static JSHandle<TaggedArray> SetCapacityInOldSpace(const JSThread *thread, const JSHandle<TaggedArray> &array, 71 uint32_t capa); 72 73 static inline void RemoveElementByIndex(const JSThread *thread, JSHandle<TaggedArray> &srcArray, 74 uint32_t index, uint32_t effectiveLength); 75 static inline void InsertElementByIndex(const JSThread *thread, JSHandle<TaggedArray> &srcArray, 76 const JSHandle<JSTaggedValue> &value, uint32_t index, uint32_t effectiveLength); 77 static inline void CopyTaggedArrayElement(const JSThread *thread, JSHandle<TaggedArray> &srcElements, 78 JSHandle<TaggedArray> &dstElements, uint32_t effectiveLength); 79 80 inline void InitializeWithSpecialValue(JSTaggedValue initValue, uint32_t length, uint32_t extraLength = 0); 81 ShouldTrim(uint32_t oldLength,uint32_t newLength)82 static inline bool ShouldTrim(uint32_t oldLength, uint32_t newLength) 83 { 84 return (oldLength - newLength > MAX_END_UNUSED); 85 } 86 inline void Trim(const JSThread *thread, uint32_t newLength); 87 88 static constexpr size_t LENGTH_OFFSET = TaggedObjectSize(); 89 ACCESSORS_PRIMITIVE_FIELD(Length, uint32_t, LENGTH_OFFSET, EXTRA_LENGTH_OFFSET) 90 ACCESSORS_PRIMITIVE_FIELD(ExtraLength, uint32_t, EXTRA_LENGTH_OFFSET, LAST_OFFSET) 91 DEFINE_ALIGN_SIZE(LAST_OFFSET); 92 static constexpr size_t DATA_OFFSET = SIZE; // DATA_OFFSET equal to Empty Array size 93 94 DECL_VISIT_ARRAY(DATA_OFFSET, GetLength(), GetLength()); 95 DECL_DUMP() 96 97 private: 98 friend class ObjectFactory; 99 }; 100 101 static_assert(TaggedArray::LENGTH_OFFSET == sizeof(TaggedObject)); 102 static_assert((TaggedArray::DATA_OFFSET % static_cast<uint8_t>(MemAlignment::MEM_ALIGN_OBJECT)) == 0); 103 104 // Copy On Write TaggedArray is shared in the nonmovable space. 105 class COWTaggedArray : public TaggedArray { 106 public: 107 CAST_CHECK(COWTaggedArray, IsCOWArray) 108 DECL_DUMP() 109 private: 110 friend class ObjectFactory; 111 }; 112 113 // A Mutant of TaggedArray which has numbers directly stored in Data section. 114 // Used by JSArrays with specified elementsKind. 115 class MutantTaggedArray : public TaggedArray { 116 public: 117 inline void InitializeWithSpecialValue(JSTaggedType initValue, uint32_t length, uint32_t extraLength = 0); 118 119 DECL_VISIT_ARRAY(DATA_OFFSET, 0, GetLength()); 120 CAST_CHECK(MutantTaggedArray, IsMutantTaggedArray) 121 DECL_DUMP() 122 private: 123 friend class ObjectFactory; 124 }; 125 126 // Copy On Write MutantTaggedArray is shared in the nonmovable space. 127 // With raw numbers stored in Data section. 128 class COWMutantTaggedArray : public MutantTaggedArray { 129 public: 130 131 DECL_VISIT_ARRAY(DATA_OFFSET, 0, GetLength()); 132 CAST_CHECK(COWMutantTaggedArray, IsCOWArray) 133 DECL_DUMP() 134 private: 135 friend class ObjectFactory; 136 }; 137 138 } // namespace panda::ecmascript 139 #endif // ECMASCRIPT_TAGGED_ARRAY_H 140