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/js_hclass.h" 20 #include "ecmascript/js_tagged_value.h" 21 #include "ecmascript/js_thread.h" 22 23 namespace panda::ecmascript { 24 class ObjectFactory; 25 26 class TaggedArray : public TaggedObject { 27 public: 28 static constexpr uint32_t MAX_ARRAY_INDEX = std::numeric_limits<uint32_t>::max(); 29 static constexpr uint32_t MAX_END_UNUSED = 4; 30 Cast(ObjectHeader * obj)31 inline static TaggedArray *Cast(ObjectHeader *obj) 32 { 33 ASSERT(JSTaggedValue(obj).IsTaggedArray()); 34 return static_cast<TaggedArray *>(obj); 35 } 36 37 JSTaggedValue Get(uint32_t idx) const; 38 39 uint32_t GetIdx(const JSTaggedValue &value) const; 40 41 template<typename T> 42 void Set(const JSThread *thread, uint32_t idx, const JSHandle<T> &value); 43 44 JSTaggedValue Get(const JSThread *thread, uint32_t idx) const; 45 46 void Set(const JSThread *thread, uint32_t idx, const JSTaggedValue &value); 47 48 static inline JSHandle<TaggedArray> Append(const JSThread *thread, const JSHandle<TaggedArray> &first, 49 const JSHandle<TaggedArray> &second); 50 static inline JSHandle<TaggedArray> AppendSkipHole(const JSThread *thread, const JSHandle<TaggedArray> &first, 51 const JSHandle<TaggedArray> &second, uint32_t copyLength); 52 ComputeSize(size_t elemSize,uint32_t length)53 static inline size_t ComputeSize(size_t elemSize, uint32_t length) 54 { 55 ASSERT(elemSize != 0); 56 size_t size = DATA_OFFSET + elemSize * length; 57 #ifdef PANDA_TARGET_32 58 size_t sizeLimit = (std::numeric_limits<size_t>::max() - DATA_OFFSET) / elemSize; 59 if (UNLIKELY(sizeLimit < static_cast<size_t>(length))) { 60 return 0; 61 } 62 #endif 63 return size; 64 } 65 GetData()66 inline JSTaggedType *GetData() const 67 { 68 return reinterpret_cast<JSTaggedType *>(ToUintPtr(this) + DATA_OFFSET); 69 } 70 71 inline bool IsDictionaryMode() const; 72 73 bool HasDuplicateEntry() const; 74 75 static JSHandle<TaggedArray> SetCapacity(const JSThread *thread, const JSHandle<TaggedArray> &array, 76 uint32_t capa); 77 78 inline void InitializeWithSpecialValue(JSTaggedValue initValue, uint32_t length); 79 ShouldTrim(JSThread * thread,uint32_t oldLength,uint32_t newLength)80 static inline bool ShouldTrim(JSThread *thread, uint32_t oldLength, uint32_t newLength) 81 { 82 return (oldLength - newLength > MAX_END_UNUSED); 83 } 84 inline void Trim(JSThread *thread, uint32_t newLength); 85 86 static constexpr size_t LENGTH_OFFSET = TaggedObjectSize(); 87 ACCESSORS_PRIMITIVE_FIELD(Length, uint32_t, LENGTH_OFFSET, LAST_OFFSET) 88 DEFINE_ALIGN_SIZE(LAST_OFFSET); 89 static constexpr size_t DATA_OFFSET = SIZE; // DATA_OFFSET equal to Empty Array size 90 91 DECL_VISIT_ARRAY(DATA_OFFSET, GetLength()); 92 93 private: 94 friend class ObjectFactory; 95 }; 96 97 static_assert(TaggedArray::LENGTH_OFFSET == sizeof(TaggedObject)); 98 static_assert((TaggedArray::DATA_OFFSET % static_cast<uint8_t>(MemAlignment::MEM_ALIGN_OBJECT)) == 0); 99 } // namespace panda::ecmascript 100 #endif // ECMASCRIPT_TAGGED_ARRAY_H 101