• 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 
Set(const JSThread * thread,uint32_t idx,const JSTaggedValue & value)66 inline void TaggedArray::Set(const JSThread *thread, uint32_t idx, const JSTaggedValue &value)
67 {
68     ASSERT(idx < GetLength());
69     size_t offset = JSTaggedValue::TaggedTypeSize() * idx;
70 
71     // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
72     if (value.IsHeapObject()) {
73         Barriers::SetObject<true>(thread, GetData(), offset, value.GetRawData());
74     } else {  // NOLINTNEXTLINE(readability-misleading-indentation)
75         Barriers::SetPrimitive<JSTaggedType>(GetData(), offset, value.GetRawData());
76     }
77 }
78 
Append(const JSThread * thread,const JSHandle<TaggedArray> & first,const JSHandle<TaggedArray> & second)79 JSHandle<TaggedArray> TaggedArray::Append(const JSThread *thread, const JSHandle<TaggedArray> &first,
80                                           const JSHandle<TaggedArray> &second)
81 {
82     uint32_t firstLength = first->GetLength();
83     uint32_t secondLength = second->GetLength();
84     uint32_t length = firstLength + secondLength;
85     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
86     JSHandle<TaggedArray> argument = factory->NewTaggedArray(length);
87     uint32_t index = 0;
88     for (; index < firstLength; ++index) {
89         argument->Set(thread, index, first->Get(index));
90     }
91     for (; index < length; ++index) {
92         argument->Set(thread, index, second->Get(index - firstLength));
93     }
94     return argument;
95 }
96 
AppendSkipHole(const JSThread * thread,const JSHandle<TaggedArray> & first,const JSHandle<TaggedArray> & second,uint32_t copyLength)97 JSHandle<TaggedArray> TaggedArray::AppendSkipHole(const JSThread *thread, const JSHandle<TaggedArray> &first,
98                                                   const JSHandle<TaggedArray> &second, uint32_t copyLength)
99 {
100     uint32_t firstLength = first->GetLength();
101     uint32_t secondLength = second->GetLength();
102     ASSERT(firstLength + secondLength >= copyLength);
103 
104     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
105     JSHandle<TaggedArray> argument = factory->NewTaggedArray(copyLength);
106     uint32_t index = 0;
107     for (; index < firstLength; ++index) {
108         JSTaggedValue val = first->Get(index);
109         if (val.IsHole()) {
110             break;
111         }
112         argument->Set(thread, index, val);
113         ASSERT(copyLength >= index);
114     }
115     for (uint32_t i = 0; i < secondLength; ++i) {
116         JSTaggedValue val = second->Get(i);
117         if (val.IsHole()) {
118             break;
119         }
120         argument->Set(thread, index++, val);
121         ASSERT(copyLength >= index);
122     }
123     return argument;
124 }
125 
HasDuplicateEntry()126 inline bool TaggedArray::HasDuplicateEntry() const
127 {
128     uint32_t length = GetLength();
129     for (uint32_t i = 0; i < length; i++) {
130         for (uint32_t j = i + 1; j < length; j++) {
131             if (JSTaggedValue::SameValue(Get(i), Get(j))) {
132                 return true;
133             }
134         }
135     }
136     return false;
137 }
138 
InitializeWithSpecialValue(JSTaggedValue initValue,uint32_t length,uint32_t extraLength)139 void TaggedArray::InitializeWithSpecialValue(JSTaggedValue initValue, uint32_t length, uint32_t extraLength)
140 {
141     ASSERT(initValue.IsSpecial());
142     SetLength(length);
143     SetExtraLength(extraLength);
144     for (uint32_t i = 0; i < length; i++) {
145         size_t offset = JSTaggedValue::TaggedTypeSize() * i;
146         Barriers::SetPrimitive<JSTaggedType>(GetData(), offset, initValue.GetRawData());
147     }
148 }
149 
SetCapacity(const JSThread * thread,const JSHandle<TaggedArray> & array,uint32_t capa)150 inline JSHandle<TaggedArray> TaggedArray::SetCapacity(const JSThread *thread, const JSHandle<TaggedArray> &array,
151                                                       uint32_t capa)
152 {
153     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
154     uint32_t oldLength = array->GetLength();
155     JSHandle<TaggedArray> newArray = factory->CopyArray(array, oldLength, capa);
156     return newArray;
157 }
158 
SetCapacityInOldSpace(const JSThread * thread,const JSHandle<TaggedArray> & array,uint32_t capa)159 inline JSHandle<TaggedArray> TaggedArray::SetCapacityInOldSpace(const JSThread *thread,
160                                                                 const JSHandle<TaggedArray> &array, uint32_t capa)
161 {
162     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
163     uint32_t oldLength = array->GetLength();
164     JSHandle<TaggedArray> newArray =
165         factory->CopyArray(array, oldLength, capa, JSTaggedValue::Hole(), MemSpaceType::OLD_SPACE);
166     return newArray;
167 }
168 
IsDictionaryMode()169 inline bool TaggedArray::IsDictionaryMode() const
170 {
171     return GetClass()->IsDictionary();
172 }
173 
Trim(JSThread * thread,uint32_t newLength)174 void TaggedArray::Trim(JSThread *thread, uint32_t newLength)
175 {
176     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
177     uint32_t oldLength = GetLength();
178     ASSERT(oldLength > newLength);
179     size_t trimBytes = (oldLength - newLength) * JSTaggedValue::TaggedTypeSize();
180     size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), newLength);
181     factory->FillFreeObject(ToUintPtr(this) + size, trimBytes, RemoveSlots::YES, ToUintPtr(this));
182     SetLength(newLength);
183 }
184 }  // namespace panda::ecmascript
185 #endif  // ECMASCRIPT_TAGGED_ARRAY_INL_H
186