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