• 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_INL_H
17 #define ECMASCRIPT_TAGGED_ARRAY_INL_H
18 
19 #include "ecmascript/js_tagged_value-inl.h"
20 #include "ecmascript/js_thread.h"
21 #include "ecmascript/object_factory.h"
22 #include "ecmascript/tagged_array.h"
23 
24 namespace panda::ecmascript {
Get(uint32_t idx)25 inline JSTaggedValue TaggedArray::Get(uint32_t idx) const
26 {
27     ASSERT(idx < GetLength());
28     // Note: Here we can't statically decide the element type is a primitive or heap object, especially for
29     //       dynamically-typed languages like JavaScript. So we simply skip the read-barrier.
30     size_t offset = JSTaggedValue::TaggedTypeSize() * idx;
31     // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
32     return JSTaggedValue(Barriers::GetValue<JSTaggedType>(GetData(), offset));
33 }
34 
Get(const JSThread * thread,uint32_t idx)35 inline JSTaggedValue TaggedArray::Get([[maybe_unused]] const JSThread *thread, uint32_t idx) const
36 {
37     return Get(idx);
38 }
39 
GetIdx(const JSTaggedValue & value)40 inline uint32_t TaggedArray::GetIdx(const JSTaggedValue &value) const
41 {
42     uint32_t length = GetLength();
43 
44     for (uint32_t i = 0; i < length; i++) {
45         if (JSTaggedValue::SameValue(Get(i), value)) {
46             return i;
47         }
48     }
49     return TaggedArray::MAX_ARRAY_INDEX;
50 }
51 
52 template<typename T>
Set(const JSThread * thread,uint32_t idx,const JSHandle<T> & value)53 inline void TaggedArray::Set(const JSThread *thread, uint32_t idx, const JSHandle<T> &value)
54 {
55     ASSERT(idx < GetLength());
56     size_t offset = JSTaggedValue::TaggedTypeSize() * idx;
57 
58     // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
59     if (value.GetTaggedValue().IsHeapObject()) {
60         Barriers::SetObject<true>(thread, GetData(), offset, value.GetTaggedValue().GetRawData());
61     } else {  // NOLINTNEXTLINE(readability-misleading-indentation)
62         Barriers::SetPrimitive<JSTaggedType>(GetData(), offset, value.GetTaggedValue().GetRawData());
63     }
64 }
65 
66 template <bool needBarrier>
Set(const JSThread * thread,uint32_t idx,const JSTaggedValue & value)67 inline void TaggedArray::Set(const JSThread *thread, uint32_t idx, const JSTaggedValue &value)
68 {
69     ASSERT(idx < GetLength());
70     size_t offset = JSTaggedValue::TaggedTypeSize() * idx;
71 
72     // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
73     if (needBarrier && value.IsHeapObject()) {
74         Barriers::SetObject<true>(thread, GetData(), offset, value.GetRawData());
75     } else {  // NOLINTNEXTLINE(readability-misleading-indentation)
76         Barriers::SetPrimitive<JSTaggedType>(GetData(), offset, value.GetRawData());
77     }
78 }
79 
Append(const JSThread * thread,const JSHandle<TaggedArray> & first,const JSHandle<TaggedArray> & second)80 JSHandle<TaggedArray> TaggedArray::Append(const JSThread *thread, const JSHandle<TaggedArray> &first,
81                                           const JSHandle<TaggedArray> &second)
82 {
83     uint32_t firstLength = first->GetLength();
84     uint32_t secondLength = second->GetLength();
85     uint32_t length = firstLength + secondLength;
86     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
87     JSHandle<TaggedArray> argument = factory->NewTaggedArray(length);
88     uint32_t index = 0;
89     for (; index < firstLength; ++index) {
90         argument->Set(thread, index, first->Get(index));
91     }
92     for (; index < length; ++index) {
93         argument->Set(thread, index, second->Get(index - firstLength));
94     }
95     return argument;
96 }
97 
AppendSkipHole(const JSThread * thread,const JSHandle<TaggedArray> & first,const JSHandle<TaggedArray> & second,uint32_t copyLength)98 JSHandle<TaggedArray> TaggedArray::AppendSkipHole(const JSThread *thread, const JSHandle<TaggedArray> &first,
99                                                   const JSHandle<TaggedArray> &second, uint32_t copyLength)
100 {
101     uint32_t firstLength = first->GetLength();
102     uint32_t secondLength = second->GetLength();
103     ASSERT(firstLength + secondLength >= copyLength);
104 
105     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
106     JSHandle<TaggedArray> argument = factory->NewTaggedArray(copyLength);
107     uint32_t index = 0;
108     for (; index < firstLength; ++index) {
109         JSTaggedValue val = first->Get(index);
110         if (val.IsHole()) {
111             break;
112         }
113         argument->Set(thread, index, val);
114         ASSERT(copyLength >= index);
115     }
116     for (uint32_t i = 0; i < secondLength; ++i) {
117         JSTaggedValue val = second->Get(i);
118         if (val.IsHole()) {
119             break;
120         }
121         argument->Set(thread, index++, val);
122         ASSERT(copyLength >= index);
123     }
124     return argument;
125 }
126 
HasDuplicateEntry()127 inline bool TaggedArray::HasDuplicateEntry() const
128 {
129     uint32_t length = GetLength();
130     for (uint32_t i = 0; i < length; i++) {
131         for (uint32_t j = i + 1; j < length; j++) {
132             if (JSTaggedValue::SameValue(Get(i), Get(j))) {
133                 return true;
134             }
135         }
136     }
137     return false;
138 }
139 
InitializeWithSpecialValue(JSTaggedValue initValue,uint32_t length,uint32_t extraLength)140 void TaggedArray::InitializeWithSpecialValue(JSTaggedValue initValue, uint32_t length, uint32_t extraLength)
141 {
142     ASSERT(initValue.IsSpecial());
143     SetLength(length);
144     SetExtraLength(extraLength);
145     for (uint32_t i = 0; i < length; i++) {
146         size_t offset = JSTaggedValue::TaggedTypeSize() * i;
147         Barriers::SetPrimitive<JSTaggedType>(GetData(), offset, initValue.GetRawData());
148     }
149 }
150 
SetCapacity(const JSThread * thread,const JSHandle<TaggedArray> & array,uint32_t capa)151 inline JSHandle<TaggedArray> TaggedArray::SetCapacity(const JSThread *thread, const JSHandle<TaggedArray> &array,
152                                                       uint32_t capa)
153 {
154     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
155     uint32_t oldLength = array->GetLength();
156     JSHandle<TaggedArray> newArray = factory->CopyArray(array, oldLength, capa);
157     return newArray;
158 }
159 
SetCapacityInOldSpace(const JSThread * thread,const JSHandle<TaggedArray> & array,uint32_t capa)160 inline JSHandle<TaggedArray> TaggedArray::SetCapacityInOldSpace(const JSThread *thread,
161                                                                 const JSHandle<TaggedArray> &array, uint32_t capa)
162 {
163     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
164     uint32_t oldLength = array->GetLength();
165     JSHandle<TaggedArray> newArray =
166         factory->CopyArray(array, oldLength, capa, JSTaggedValue::Hole(), MemSpaceType::OLD_SPACE);
167     return newArray;
168 }
169 
RemoveElementByIndex(const JSThread * thread,JSHandle<TaggedArray> & srcArray,uint32_t index,uint32_t effectiveLength)170 void TaggedArray::RemoveElementByIndex(const JSThread *thread, JSHandle<TaggedArray> &srcArray,
171                                        uint32_t index, uint32_t effectiveLength)
172 {
173     ASSERT(0 <= index || index < effectiveLength);
174     Region *region = Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(*srcArray));
175     if (region->InYoungSpace() && !region->IsMarking()) {
176         size_t taggedTypeSize = JSTaggedValue::TaggedTypeSize();
177         size_t offset = taggedTypeSize * index;
178         auto *addr = reinterpret_cast<JSTaggedType *>(ToUintPtr(srcArray->GetData()) + offset);
179         while (index < effectiveLength - 1) {
180             *addr = *(addr + 1);
181             addr++;
182             index++;
183         }
184     } else {
185         while (index < effectiveLength - 1) {
186             srcArray->Set(thread, index, srcArray->Get(index + 1));
187             index++;
188         }
189     }
190     srcArray->Set(thread, effectiveLength - 1, JSTaggedValue::Hole());
191 }
192 
InsertElementByIndex(const JSThread * thread,JSHandle<TaggedArray> & srcArray,const JSHandle<JSTaggedValue> & value,uint32_t index,uint32_t effectiveLength)193 void TaggedArray::InsertElementByIndex(const JSThread *thread, JSHandle<TaggedArray> &srcArray,
194     const JSHandle<JSTaggedValue> &value, uint32_t index, uint32_t effectiveLength)
195 {
196     ASSERT(0 <= index || index <= effectiveLength);
197     ASSERT(effectiveLength < srcArray->GetLength());
198     Region *region = Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(*srcArray));
199     if (region->InYoungSpace() && !region->IsMarking()) {
200         size_t taggedTypeSize = JSTaggedValue::TaggedTypeSize();
201         size_t offset = taggedTypeSize * effectiveLength;
202         auto *addr = reinterpret_cast<JSTaggedType *>(ToUintPtr(srcArray->GetData()) + offset);
203         while (effectiveLength != index && effectiveLength > 0) {
204             *addr = *(addr - 1);
205             addr--;
206             effectiveLength--;
207         }
208     } else {
209         while (effectiveLength != index && effectiveLength > 0) {
210             JSTaggedValue oldValue = srcArray->Get(effectiveLength - 1);
211             srcArray->Set(thread, effectiveLength, oldValue);
212             effectiveLength--;
213         }
214     }
215     srcArray->Set(thread, index, value.GetTaggedValue());
216 }
217 
CopyTaggedArrayElement(const JSThread * thread,JSHandle<TaggedArray> & srcElements,JSHandle<TaggedArray> & dstElements,uint32_t effectiveLength)218 void TaggedArray::CopyTaggedArrayElement(const JSThread *thread, JSHandle<TaggedArray> &srcElements,
219                                          JSHandle<TaggedArray> &dstElements, uint32_t effectiveLength)
220 {
221     ASSERT(effectiveLength <= srcElements->GetLength());
222     ASSERT(effectiveLength <= dstElements->GetLength());
223     Region *region = Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(*dstElements));
224     if (region->InYoungSpace() && !region->IsMarking()) {
225         size_t size = effectiveLength * sizeof(JSTaggedType);
226         if (memcpy_s(reinterpret_cast<void *>(dstElements->GetData()), size,
227             reinterpret_cast<void *>(srcElements->GetData()), size) != EOK) {
228             LOG_FULL(FATAL) << "memcpy_s failed" << " size: " << size;
229         }
230     } else {
231         for (uint32_t i = 0; i < effectiveLength; i++) {
232             dstElements->Set(thread, i, srcElements->Get(i));
233         }
234     }
235 }
236 
IsDictionaryMode()237 inline bool TaggedArray::IsDictionaryMode() const
238 {
239     return GetClass()->IsDictionary();
240 }
241 
Trim(const JSThread * thread,uint32_t newLength)242 void TaggedArray::Trim(const JSThread *thread, uint32_t newLength)
243 {
244     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
245     uint32_t oldLength = GetLength();
246     ASSERT(oldLength > newLength);
247     size_t trimBytes = (oldLength - newLength) * JSTaggedValue::TaggedTypeSize();
248     size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), newLength);
249     factory->FillFreeObject(ToUintPtr(this) + size, trimBytes, RemoveSlots::YES, ToUintPtr(this));
250     SetLength(newLength);
251 }
252 }  // namespace panda::ecmascript
253 #endif  // ECMASCRIPT_TAGGED_ARRAY_INL_H
254