• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 #define ECMASCRIPT_TAGGED_ARRAY_CPP
17 
18 #include "ecmascript/tagged_array.h"
19 #include "ecmascript/tagged_array-inl.h"
20 
21 #include "ecmascript/object_factory.h"
22 
23 namespace panda::ecmascript {
24 
Get(const JSThread * thread,uint32_t idx) const25 JSTaggedValue TaggedArray::Get([[maybe_unused]] const JSThread *thread, uint32_t idx) const
26 {
27     return Get(idx);
28 }
29 
GetIdx(const JSTaggedValue & value) const30 uint32_t TaggedArray::GetIdx(const JSTaggedValue &value) const
31 {
32     uint32_t length = GetLength();
33 
34     for (uint32_t i = 0; i < length; i++) {
35         if (JSTaggedValue::SameValue(Get(i), value)) {
36             return i;
37         }
38     }
39     return TaggedArray::MAX_ARRAY_INDEX;
40 }
41 
GetBit(uint32_t idx,uint32_t bitOffset) const42 JSTaggedValue TaggedArray::GetBit(uint32_t idx, uint32_t bitOffset) const
43 {
44     ASSERT(idx < GetLength());
45     JSTaggedType element = Get(idx).GetRawData();
46     return JSTaggedValue(int((element >> bitOffset) & 1ULL));
47 }
48 
49 
SetBit(const JSThread * thread,uint32_t idx,uint32_t bitOffset,const JSTaggedValue & value)50 void TaggedArray::SetBit(const JSThread *thread, uint32_t idx, uint32_t bitOffset, const JSTaggedValue &value)
51 {
52     ASSERT(idx < GetLength());
53     JSTaggedType element = Get(idx).GetRawData();
54     if (value.IsZero()) {
55         element &= ~(1ULL << bitOffset);
56     } else {
57         element |= (1ULL << bitOffset);
58     }
59     Set<false>(thread, idx, JSTaggedValue(element));
60 }
61 
Set(uint32_t idx,const JSTaggedValue & value)62 void TaggedArray::Set(uint32_t idx, const JSTaggedValue &value)
63 {
64     ASSERT(idx < GetLength());
65     ASSERT(!value.IsHeapObject());
66     size_t offset = JSTaggedValue::TaggedTypeSize() * idx;
67 
68     Barriers::SetPrimitive<JSTaggedType>(GetData(), offset, value.GetRawData());
69 }
70 
Append(const JSThread * thread,const JSHandle<TaggedArray> & first,const JSHandle<TaggedArray> & second)71 JSHandle<TaggedArray> TaggedArray::Append(const JSThread *thread, const JSHandle<TaggedArray> &first,
72                                           const JSHandle<TaggedArray> &second)
73 {
74     uint32_t firstLength = first->GetLength();
75     uint32_t secondLength = second->GetLength();
76     uint32_t length = firstLength + secondLength;
77     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
78     JSHandle<TaggedArray> argument = factory->NewTaggedArray(length);
79     uint32_t index = 0;
80     for (; index < firstLength; ++index) {
81         argument->Set(thread, index, first->Get(index));
82     }
83     for (; index < length; ++index) {
84         argument->Set(thread, index, second->Get(index - firstLength));
85     }
86     return argument;
87 }
88 
AppendSkipHole(const JSThread * thread,const JSHandle<TaggedArray> & first,const JSHandle<TaggedArray> & second,uint32_t copyLength)89 JSHandle<TaggedArray> TaggedArray::AppendSkipHole(const JSThread *thread, const JSHandle<TaggedArray> &first,
90                                                   const JSHandle<TaggedArray> &second, uint32_t copyLength)
91 {
92     uint32_t firstLength = first->GetLength();
93     uint32_t secondLength = second->GetLength();
94     ASSERT(firstLength + secondLength >= copyLength);
95 
96     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
97     JSHandle<TaggedArray> argument = factory->NewTaggedArray(copyLength);
98     uint32_t index = 0;
99     for (; index < firstLength; ++index) {
100         JSTaggedValue val = first->Get(index);
101         if (val.IsHole()) {
102             break;
103         }
104         argument->Set(thread, index, val);
105         ASSERT(copyLength >= index);
106     }
107     for (uint32_t i = 0; i < secondLength; ++i) {
108         JSTaggedValue val = second->Get(i);
109         if (val.IsHole()) {
110             break;
111         }
112         argument->Set(thread, index++, val);
113         ASSERT(copyLength >= index);
114     }
115     return argument;
116 }
117 
HasDuplicateEntry() const118 bool TaggedArray::HasDuplicateEntry() const
119 {
120     uint32_t length = GetLength();
121     for (uint32_t i = 0; i < length; i++) {
122         for (uint32_t j = i + 1; j < length; j++) {
123             if (JSTaggedValue::SameValue(Get(i), Get(j))) {
124                 return true;
125             }
126         }
127     }
128     return false;
129 }
130 
InitializeWithSpecialValue(JSTaggedValue initValue,uint32_t length,uint32_t extraLength)131 void TaggedArray::InitializeWithSpecialValue(JSTaggedValue initValue, uint32_t length, uint32_t extraLength)
132 {
133     SetLength(length);
134     SetExtraLength(extraLength);
135     FillRangeWithSpecialValue(initValue, 0, length);
136 }
137 
FillRangeWithSpecialValue(JSTaggedValue initValue,uint32_t start,uint32_t end)138 void TaggedArray::FillRangeWithSpecialValue(JSTaggedValue initValue, uint32_t start, uint32_t end)
139 {
140     ASSERT(initValue.IsSpecial());
141     for (uint32_t i = start; i < end; i++) {
142         size_t offset = JSTaggedValue::TaggedTypeSize() * i;
143         Barriers::SetPrimitive<JSTaggedType>(GetData(), offset, initValue.GetRawData());
144     }
145 }
146 
SetCapacity(const JSThread * thread,const JSHandle<TaggedArray> & array,uint32_t capa)147 JSHandle<TaggedArray> TaggedArray::SetCapacity(const JSThread *thread, const JSHandle<TaggedArray> &array,
148                                                uint32_t capa)
149 {
150     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
151     uint32_t oldLength = array->GetLength();
152     JSHandle<TaggedArray> newArray = factory->CopyArray(array, oldLength, capa);
153     return newArray;
154 }
155 
SetCapacityInOldSpace(const JSThread * thread,const JSHandle<TaggedArray> & array,uint32_t capa)156 JSHandle<TaggedArray> TaggedArray::SetCapacityInOldSpace(const JSThread *thread,
157                                                          const JSHandle<TaggedArray> &array, uint32_t capa)
158 {
159     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
160     uint32_t oldLength = array->GetLength();
161     JSHandle<TaggedArray> newArray =
162         factory->CopyArray(array, oldLength, capa, JSTaggedValue::Hole(), MemSpaceType::OLD_SPACE);
163     return newArray;
164 }
165 
RemoveElementByIndex(const JSThread * thread,JSHandle<TaggedArray> & srcArray,uint32_t index,uint32_t effectiveLength,bool noNeedBarrier)166 void TaggedArray::RemoveElementByIndex(const JSThread *thread, JSHandle<TaggedArray> &srcArray,
167                                        uint32_t index, uint32_t effectiveLength, bool noNeedBarrier)
168 {
169     ASSERT(0 <= index || index < effectiveLength);
170     ASSERT(effectiveLength > 0);
171     if (noNeedBarrier) {
172         size_t taggedTypeSize = JSTaggedValue::TaggedTypeSize();
173         size_t offset = taggedTypeSize * index;
174         auto *addr = reinterpret_cast<JSTaggedType *>(ToUintPtr(srcArray->GetData()) + offset);
175         while (index < effectiveLength - 1) {
176             *addr = *(addr + 1);
177             addr++;
178             index++;
179         }
180     } else {
181         while (index < effectiveLength - 1) {
182             srcArray->Set(thread, index, srcArray->Get(index + 1));
183             index++;
184         }
185     }
186     srcArray->Set(thread, effectiveLength - 1, JSTaggedValue::Hole());
187 }
188 
InsertElementByIndex(const JSThread * thread,JSHandle<TaggedArray> & srcArray,const JSHandle<JSTaggedValue> & value,uint32_t index,uint32_t effectiveLength)189 void TaggedArray::InsertElementByIndex(const JSThread *thread, JSHandle<TaggedArray> &srcArray,
190     const JSHandle<JSTaggedValue> &value, uint32_t index, uint32_t effectiveLength)
191 {
192     ASSERT(0 <= index || index <= effectiveLength);
193     ASSERT(effectiveLength < srcArray->GetLength());
194     while (effectiveLength != index && effectiveLength > 0) {
195         JSTaggedValue oldValue = srcArray->Get(effectiveLength - 1);
196         srcArray->Set(thread, effectiveLength, oldValue);
197         effectiveLength--;
198     }
199     srcArray->Set(thread, index, value.GetTaggedValue());
200 }
201 
CopyTaggedArrayElement(const JSThread * thread,JSHandle<TaggedArray> & srcElements,JSHandle<TaggedArray> & dstElements,uint32_t effectiveLength)202 void TaggedArray::CopyTaggedArrayElement(const JSThread *thread, JSHandle<TaggedArray> &srcElements,
203                                          JSHandle<TaggedArray> &dstElements, uint32_t effectiveLength)
204 {
205     ASSERT(effectiveLength <= srcElements->GetLength());
206     ASSERT(effectiveLength <= dstElements->GetLength());
207     for (uint32_t i = 0; i < effectiveLength; i++) {
208         dstElements->Set(thread, i, srcElements->Get(i));
209     }
210 }
211 
IsDictionaryMode() const212 bool TaggedArray::IsDictionaryMode() const
213 {
214     return GetClass()->IsDictionary();
215 }
216 
IsGeneralNewAndNotMarking(const JSThread * thread)217 bool TaggedArray::IsGeneralNewAndNotMarking(const JSThread *thread)
218 {
219     Region *region = Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(this));
220     return region->InGeneralNewSpace() && !thread->IsConcurrentMarkingOrFinished();
221 }
222 
Trim(const JSThread * thread,uint32_t newLength)223 void TaggedArray::Trim(const JSThread *thread, uint32_t newLength)
224 {
225     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
226     uint32_t oldLength = GetLength();
227     ASSERT(oldLength > newLength);
228     size_t trimBytes = (oldLength - newLength) * JSTaggedValue::TaggedTypeSize();
229     size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), newLength);
230     factory->FillFreeObject(ToUintPtr(this) + size, trimBytes, RemoveSlots::YES, ToUintPtr(this));
231     SetLength(newLength);
232 }
233 
InitializeWithSpecialValue(JSTaggedType initValue,uint32_t length,uint32_t extraLength)234 void MutantTaggedArray::InitializeWithSpecialValue(JSTaggedType initValue, uint32_t length, uint32_t extraLength)
235 {
236     SetLength(length);
237     SetExtraLength(extraLength);
238     for (uint32_t i = 0; i < length; i++) {
239         size_t offset = JSTaggedValue::TaggedTypeSize() * i;
240         // NOLINTNEXTLINE(readability-misleading-indentation)
241         Barriers::SetPrimitive<JSTaggedType>(GetData(), offset, initValue);
242     }
243 }
244 }  // namespace panda::ecmascript
245