• 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/tagged_array.h"
22 
23 namespace panda::ecmascript {
Get(uint32_t idx)24 inline JSTaggedValue TaggedArray::Get(uint32_t idx) const
25 {
26     ASSERT(idx < GetLength());
27     // Note: Here we can't statically decide the element type is a primitive or heap object, especially for
28     //       dynamically-typed languages like JavaScript. So we simply skip the read-barrier.
29     size_t offset = JSTaggedValue::TaggedTypeSize() * idx;
30     // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
31     return JSTaggedValue(Barriers::GetDynValue<JSTaggedType>(GetData(), offset));
32 }
33 
Get(const JSThread * thread,uint32_t idx)34 inline JSTaggedValue TaggedArray::Get([[maybe_unused]] const JSThread *thread, uint32_t idx) const
35 {
36     return Get(idx);
37 }
38 
GetIdx(const JSTaggedValue & value)39 inline uint32_t TaggedArray::GetIdx(const JSTaggedValue &value) const
40 {
41     uint32_t length = GetLength();
42 
43     for (uint32_t i = 0; i < length; i++) {
44         if (JSTaggedValue::SameValue(Get(i), value)) {
45             return i;
46         }
47     }
48     return TaggedArray::MAX_ARRAY_INDEX;
49 }
50 
51 template<typename T>
Set(const JSThread * thread,uint32_t idx,const JSHandle<T> & value)52 inline void TaggedArray::Set(const JSThread *thread, uint32_t idx, const JSHandle<T> &value)
53 {
54     ASSERT(idx < GetLength());
55     size_t offset = JSTaggedValue::TaggedTypeSize() * idx;
56 
57     // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
58     if (value.GetTaggedValue().IsHeapObject()) {
59         Barriers::SetDynObject<true>(thread, GetData(), offset, value.GetTaggedValue().GetRawData());
60     } else {  // NOLINTNEXTLINE(readability-misleading-indentation)
61         Barriers::SetDynPrimitive<JSTaggedType>(GetData(), offset, value.GetTaggedValue().GetRawData());
62     }
63 }
64 
Set(const JSThread * thread,uint32_t idx,const JSTaggedValue & value)65 inline void TaggedArray::Set(const JSThread *thread, uint32_t idx, const JSTaggedValue &value)
66 {
67     ASSERT(idx < GetLength());
68     size_t offset = JSTaggedValue::TaggedTypeSize() * idx;
69 
70     // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
71     if (value.IsHeapObject()) {
72         Barriers::SetDynObject<true>(thread, GetData(), offset, value.GetRawData());
73     } else {  // NOLINTNEXTLINE(readability-misleading-indentation)
74         Barriers::SetDynPrimitive<JSTaggedType>(GetData(), offset, value.GetRawData());
75     }
76 }
77 
Append(const JSThread * thread,const JSHandle<TaggedArray> & first,const JSHandle<TaggedArray> & second)78 JSHandle<TaggedArray> TaggedArray::Append(const JSThread *thread, const JSHandle<TaggedArray> &first,
79                                           const JSHandle<TaggedArray> &second)
80 {
81     uint32_t firstLength = first->GetLength();
82     uint32_t secondLength = second->GetLength();
83     uint32_t length = firstLength + secondLength;
84     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
85     JSHandle<TaggedArray> argument = factory->NewTaggedArray(length);
86     uint32_t index = 0;
87     for (; index < firstLength; ++index) {
88         argument->Set(thread, index, first->Get(index));
89     }
90     for (; index < length; ++index) {
91         argument->Set(thread, index, second->Get(index - firstLength));
92     }
93     return argument;
94 }
95 
AppendSkipHole(const JSThread * thread,const JSHandle<TaggedArray> & first,const JSHandle<TaggedArray> & second,uint32_t copyLength)96 JSHandle<TaggedArray> TaggedArray::AppendSkipHole(const JSThread *thread, const JSHandle<TaggedArray> &first,
97                                                   const JSHandle<TaggedArray> &second, uint32_t copyLength)
98 {
99     uint32_t firstLength = first->GetLength();
100     uint32_t secondLength = second->GetLength();
101     ASSERT(firstLength + secondLength >= copyLength);
102 
103     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
104     JSHandle<TaggedArray> argument = factory->NewTaggedArray(copyLength);
105     uint32_t index = 0;
106     for (; index < firstLength; ++index) {
107         JSTaggedValue val = first->Get(index);
108         if (val.IsHole()) {
109             break;
110         }
111         argument->Set(thread, index, val);
112         ASSERT(copyLength >= index);
113     }
114     for (uint32_t i = 0; i < secondLength; ++i) {
115         JSTaggedValue val = second->Get(i);
116         if (val.IsHole()) {
117             break;
118         }
119         argument->Set(thread, index++, val);
120         ASSERT(copyLength >= index);
121     }
122     return argument;
123 }
124 
HasDuplicateEntry()125 inline bool TaggedArray::HasDuplicateEntry() const
126 {
127     uint32_t length = GetLength();
128     for (uint32_t i = 0; i < length; i++) {
129         for (uint32_t j = i + 1; j < length; j++) {
130             if (JSTaggedValue::SameValue(Get(i), Get(j))) {
131                 return true;
132             }
133         }
134     }
135     return false;
136 }
137 
InitializeWithSpecialValue(JSTaggedValue initValue,uint32_t length)138 void TaggedArray::InitializeWithSpecialValue(JSTaggedValue initValue, uint32_t length)
139 {
140     ASSERT(initValue.IsSpecial());
141     SetLength(length);
142     for (uint32_t i = 0; i < length; i++) {
143         size_t offset = JSTaggedValue::TaggedTypeSize() * i;
144         Barriers::SetDynPrimitive<JSTaggedType>(GetData(), offset, initValue.GetRawData());
145     }
146 }
147 
SetCapacity(const JSThread * thread,const JSHandle<TaggedArray> & array,uint32_t capa)148 inline JSHandle<TaggedArray> TaggedArray::SetCapacity(const JSThread *thread, const JSHandle<TaggedArray> &array,
149                                                       uint32_t capa)
150 {
151     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
152     uint32_t oldLength = array->GetLength();
153     JSHandle<TaggedArray> newArray = factory->CopyArray(array, oldLength, capa);
154     return newArray;
155 }
156 
IsDictionaryMode()157 inline bool TaggedArray::IsDictionaryMode() const
158 {
159     return GetClass()->IsDictionary();
160 }
161 
Trim(JSThread * thread,uint32_t newLength)162 void TaggedArray::Trim(JSThread *thread, uint32_t newLength)
163 {
164     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
165     uint32_t oldLength = GetLength();
166     ASSERT(oldLength > newLength);
167     size_t trimBytes = (oldLength - newLength) * JSTaggedValue::TaggedTypeSize();
168     size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), newLength);
169     factory->FillFreeObject(ToUintPtr(this) + size, trimBytes, RemoveSlots::YES);
170     SetLength(newLength);
171 }
172 }  // namespace panda::ecmascript
173 #endif  // ECMASCRIPT_TAGGED_ARRAY_INL_H
174