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