• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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