• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #include "ecmascript/tagged_array.h"
17 #include "ecmascript/global_env.h"
18 #include "ecmascript/tests/test_helper.h"
19 
20 using namespace panda::ecmascript;
21 
22 namespace panda::test {
23 class TaggedArrayTest : public BaseTestWithScope<false> {
24 };
25 
JSArrayTestCreate(JSThread * thread)26 static JSObject *JSArrayTestCreate(JSThread *thread)
27 {
28     [[maybe_unused]] ecmascript::EcmaHandleScope scope(thread);
29     EcmaVM *ecmaVM = thread->GetEcmaVM();
30     auto globalEnv = ecmaVM->GetGlobalEnv();
31     JSHandle<JSTaggedValue> jsFunc = globalEnv->GetArrayFunction();
32     JSHandle<JSObject> newArray =
33         ecmaVM->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(jsFunc), jsFunc);
34     return *newArray;
35 }
36 
HWTEST_F_L0(TaggedArrayTest,Create)37 HWTEST_F_L0(TaggedArrayTest, Create)
38 {
39     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
40     uint32_t arrayLength = 2;
41     JSHandle<TaggedArray> taggedArray = factory->NewTaggedArray(arrayLength);
42     EXPECT_TRUE(*taggedArray != nullptr);
43     // every element of the taggedarray is JSTaggedValue::Hole()
44     for (uint32_t i = 0; i < arrayLength; i++) {
45         EXPECT_TRUE(taggedArray->Get(thread, i).IsHole());
46     }
47 }
48 
HWTEST_F_L0(TaggedArrayTest,SetAndGetIdx)49 HWTEST_F_L0(TaggedArrayTest, SetAndGetIdx)
50 {
51     EcmaVM *ecmaVM = thread->GetEcmaVM();
52     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
53     uint32_t arrayLength = 2;
54     JSHandle<TaggedArray> taggedArray = factory->NewTaggedArray(arrayLength);
55 
56     JSHandle<JSObject> newObj1(thread, JSArrayTestCreate(thread));
57     JSObject *newObj2 = JSArrayTestCreate(thread);
58     JSTaggedValue objValue(newObj2);
59     taggedArray->Set(thread, 0, newObj1);
60     taggedArray->Set(thread, 1, objValue);
61 
62     EXPECT_EQ(taggedArray->GetIdx(thread, newObj1.GetTaggedValue()), 0U);
63     EXPECT_EQ(taggedArray->GetIdx(thread, objValue), 1U);
64     // trigger gc
65     ecmaVM->CollectGarbage(TriggerGCType::OLD_GC);
66     EXPECT_EQ(taggedArray->GetIdx(thread, newObj1.GetTaggedValue()), 0U);
67     if (!g_isEnableCMCGC) {
68         // cmc gc may not evacuate tl region.
69         EXPECT_EQ(taggedArray->GetIdx(thread, objValue), TaggedArray::MAX_ARRAY_INDEX);
70     }
71 }
72 
HWTEST_F_L0(TaggedArrayTest,Append)73 HWTEST_F_L0(TaggedArrayTest, Append)
74 {
75     EcmaVM *ecmaVM = thread->GetEcmaVM();
76     ecmaVM->SetEnableForceGC(false);  // turn off GC
77     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
78     uint32_t arrayLength = 2;
79     JSHandle<TaggedArray> taggedArray1 = factory->NewTaggedArray(arrayLength);
80     JSHandle<TaggedArray> taggedArray2 = factory->NewTaggedArray(arrayLength);
81     // create value of the taggedarray
82     JSHandle<JSObject> newObj1(thread, JSArrayTestCreate(thread));
83     JSObject *newObj2 = JSArrayTestCreate(thread);
84     JSTaggedValue objValue(newObj2);
85     // set value to the taggedarray
86     taggedArray1->Set(thread, 0, newObj1);
87     taggedArray1->Set(thread, 1, JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
88     taggedArray2->Set(thread, 0, objValue);
89     taggedArray2->Set(thread, 1, JSTaggedValue::Undefined());
90     // append two taggedarray
91     JSHandle<TaggedArray> appendArray = TaggedArray::Append(thread, taggedArray1, taggedArray2);
92     EXPECT_EQ(appendArray->GetLength(), arrayLength * 2);
93     EXPECT_EQ(appendArray->Get(thread, 0), newObj1.GetTaggedValue());
94     EXPECT_EQ(appendArray->Get(thread, 2), objValue); // 2: the second index
95     EXPECT_EQ(appendArray->Get(thread, 1), appendArray->Get(thread, 3)); // 3: the third index
96     ecmaVM->SetEnableForceGC(true);  // turn on GC
97 }
98 
HWTEST_F_L0(TaggedArrayTest,AppendSkipHole)99 HWTEST_F_L0(TaggedArrayTest, AppendSkipHole)
100 {
101     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
102     uint32_t arrayLength = 2;
103     uint32_t twoArrayLength = arrayLength * 2 + 1;
104     JSHandle<TaggedArray> taggedArray1 = factory->NewTaggedArray(arrayLength + 1);
105     JSHandle<TaggedArray> taggedArray2 = factory->NewTaggedArray(arrayLength);
106     // create value of the taggedarray
107     JSHandle<JSObject> newObj1(thread, JSArrayTestCreate(thread));
108     // set value to the taggedarray
109     taggedArray1->Set(thread, 0, newObj1);
110     taggedArray1->Set(thread, 1, newObj1.GetTaggedValue());
111     taggedArray1->Set(thread, 2, JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
112     taggedArray2->Set(thread, 1, newObj1.GetTaggedValue());
113     // append two taggedarray
114     JSHandle<TaggedArray> appendArray = TaggedArray::AppendSkipHole(thread, taggedArray1, taggedArray2, twoArrayLength);
115     EXPECT_EQ(appendArray->GetLength(), twoArrayLength);
116     EXPECT_EQ(appendArray->Get(thread, 0), appendArray->Get(thread, 1));
117     EXPECT_TRUE(appendArray->Get(thread, 2).IsUndefined()); // 2: the second index
118     EXPECT_TRUE(appendArray->Get(thread, 3).IsHole()); // 3: the third index
119     EXPECT_TRUE(appendArray->Get(thread, 4).IsHole()); // 4: the fourth index
120 }
121 
HWTEST_F_L0(TaggedArrayTest,HasDuplicateEntry)122 HWTEST_F_L0(TaggedArrayTest, HasDuplicateEntry)
123 {
124     EcmaVM *ecmaVM = thread->GetEcmaVM();
125     ObjectFactory *factory = ecmaVM->GetFactory();
126     uint32_t arrayLength = 10;
127     JSHandle<TaggedArray> taggedArray = factory->NewTaggedArray(arrayLength);
128     JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(1)); // 1: means value
129     JSHandle<JSTaggedValue> value3(thread, JSTaggedValue(3)); // 3: means value
130 
131     JSHandle<JSObject> newObj1(thread, JSArrayTestCreate(thread));
132     JSObject *newObj2 = JSArrayTestCreate(thread);
133     JSTaggedValue objValue(newObj2);
134     for (uint32_t i = 0; i < arrayLength; i++) {
135         JSHandle<JSTaggedValue> arrayValue(thread, JSTaggedValue(i));
136         taggedArray->Set(thread, i, arrayValue.GetTaggedValue());
137     }
138     EXPECT_FALSE(taggedArray->HasDuplicateEntry(thread));
139     // set value that is the same as the thrid index
140     taggedArray->Set(thread, 1, value3.GetTaggedValue());
141     EXPECT_TRUE(taggedArray->HasDuplicateEntry(thread));
142     // resert value in the second index
143     taggedArray->Set(thread, 1, value1.GetTaggedValue());
144     taggedArray->Set(thread, 5, newObj1);  // 5: the fifth index
145     taggedArray->Set(thread, 6, newObj1.GetTaggedValue());  // 6: the sixth index
146     EXPECT_TRUE(taggedArray->HasDuplicateEntry(thread));
147 }
148 
HWTEST_F_L0(TaggedArrayTest,Trim)149 HWTEST_F_L0(TaggedArrayTest, Trim)
150 {
151     uint32_t oldArrayLength = 10;
152     uint32_t newArrayLength = 5;
153     auto globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
154     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
155     JSHandle<JSTaggedValue> indexValue(thread, JSTaggedValue(6));
156     JSHandle<JSTaggedValue> undefinedValue(thread, JSTaggedValue::Undefined());
157 
158     JSHandle<JSTaggedValue> jsFunc = globalEnv->GetObjectFunction();
159     JSHandle<JSObject> TaggedArrayObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(jsFunc), jsFunc);
160     // Create taggedarray with oldArrayLength
161     JSHandle<TaggedArray> taggedArray = factory->NewTaggedArray(oldArrayLength);
162     for (uint32_t i = 0; i < oldArrayLength; i++) {
163         JSHandle<JSTaggedValue> arrayValue(thread, JSTaggedValue(i));
164         taggedArray->Set(thread, i, arrayValue.GetTaggedValue());
165     }
166     TaggedArrayObj->SetElements(thread, taggedArray);
167     EXPECT_EQ(JSObject::GetProperty(thread, TaggedArrayObj, indexValue).GetValue(), indexValue);
168     // trim taggedarray
169     taggedArray->Trim(thread, newArrayLength);
170     for (uint32_t i = 0; i < newArrayLength; i++) {
171         JSHandle<JSTaggedValue> arrayValue(thread, JSTaggedValue(i));
172         EXPECT_EQ(taggedArray->Get(thread, i), arrayValue.GetTaggedValue());
173     }
174     EXPECT_EQ(taggedArray->GetLength(), newArrayLength);
175     EXPECT_EQ(JSObject::GetProperty(thread, TaggedArrayObj, indexValue).GetValue(), undefinedValue);
176 }
177 
HWTEST_F_L0(TaggedArrayTest,RemoveElementByIndex)178 HWTEST_F_L0(TaggedArrayTest, RemoveElementByIndex)
179 {
180     constexpr uint32_t ELEMENT_NUMS = 20;
181     constexpr uint32_t REMOVE_INDEX = 0;
182     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
183     JSHandle<TaggedArray> semiTaggedarray = factory->NewTaggedArray(ELEMENT_NUMS, JSTaggedValue::Hole(),
184                                                                     MemSpaceType::SEMI_SPACE);
185     JSHandle<TaggedArray> oldTaggedarray = factory->NewTaggedArray(ELEMENT_NUMS, JSTaggedValue::Hole(),
186                                                                    MemSpaceType::OLD_SPACE);
187     // init tagggedArray
188     for (uint32_t i = 0; i < ELEMENT_NUMS; i++) {
189         semiTaggedarray->Set(thread, i, JSTaggedValue(i));
190         oldTaggedarray->Set(thread, i, JSTaggedValue(i));
191     }
192     TaggedArray::RemoveElementByIndex(thread, semiTaggedarray, REMOVE_INDEX, ELEMENT_NUMS);
193     TaggedArray::RemoveElementByIndex(thread, oldTaggedarray, REMOVE_INDEX, ELEMENT_NUMS);
194 
195     for (uint32_t i = 0; i < ELEMENT_NUMS - 1; i++) {
196         EXPECT_EQ(semiTaggedarray->Get(thread, i), JSTaggedValue(i + 1));
197         EXPECT_EQ(oldTaggedarray->Get(thread, i), JSTaggedValue(i + 1));
198     }
199     EXPECT_EQ(semiTaggedarray->Get(thread, ELEMENT_NUMS - 1), JSTaggedValue::Hole());
200     EXPECT_EQ(oldTaggedarray->Get(thread, ELEMENT_NUMS - 1), JSTaggedValue::Hole());
201 }
202 
HWTEST_F_L0(TaggedArrayTest,InsertElementByIndex)203 HWTEST_F_L0(TaggedArrayTest, InsertElementByIndex)
204 {
205     constexpr uint32_t ELEMENT_NUMS = 20;
206     constexpr uint32_t INSERT_INDEX = 0;
207     JSHandle<JSTaggedValue> insertValue(thread, JSTaggedValue(ELEMENT_NUMS));
208     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
209     JSHandle<TaggedArray> semiTaggedarray = factory->NewTaggedArray(ELEMENT_NUMS, JSTaggedValue::Hole(),
210                                                                     MemSpaceType::SEMI_SPACE);
211     JSHandle<TaggedArray> oldTaggedarray = factory->NewTaggedArray(ELEMENT_NUMS, JSTaggedValue::Hole(),
212                                                                    MemSpaceType::OLD_SPACE);
213     // init tagggedArray
214     for (uint32_t i = 0; i < ELEMENT_NUMS - 1; i++) {
215         semiTaggedarray->Set(thread, i, JSTaggedValue(i));
216         oldTaggedarray->Set(thread, i, JSTaggedValue(i));
217     }
218     TaggedArray::InsertElementByIndex(thread, semiTaggedarray, insertValue, INSERT_INDEX, ELEMENT_NUMS - 1);
219     TaggedArray::InsertElementByIndex(thread, oldTaggedarray, insertValue, INSERT_INDEX, ELEMENT_NUMS - 1);
220     // check
221     EXPECT_EQ(semiTaggedarray->Get(thread, 0), insertValue.GetTaggedValue());
222     EXPECT_EQ(oldTaggedarray->Get(thread, 0), insertValue.GetTaggedValue());
223     for (uint32_t i = 1; i < ELEMENT_NUMS; i++) {
224         EXPECT_EQ(semiTaggedarray->Get(thread, i), JSTaggedValue(i - 1));
225         EXPECT_EQ(oldTaggedarray->Get(thread, i), JSTaggedValue(i - 1));
226     }
227 }
228 
HWTEST_F_L0(TaggedArrayTest,CopyTaggedArrayElement)229 HWTEST_F_L0(TaggedArrayTest, CopyTaggedArrayElement)
230 {
231     constexpr uint32_t ELEMENT_NUMS = 20;
232     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
233     JSHandle<TaggedArray> srcSemiTaggedarray = factory->NewTaggedArray(ELEMENT_NUMS, JSTaggedValue::Hole(),
234                                                                        MemSpaceType::SEMI_SPACE);
235     JSHandle<TaggedArray> srcOldTaggedarray = factory->NewTaggedArray(ELEMENT_NUMS, JSTaggedValue::Hole(),
236                                                                       MemSpaceType::OLD_SPACE);
237     JSHandle<TaggedArray> dstSemiTaggedarray = factory->NewTaggedArray(ELEMENT_NUMS);
238     JSHandle<TaggedArray> dstOldTaggedarray = factory->NewTaggedArray(ELEMENT_NUMS);
239     // init tagggedArray
240     for (uint32_t i = 0; i < ELEMENT_NUMS; i++) {
241         srcSemiTaggedarray->Set(thread, i, JSTaggedValue(i));
242         srcOldTaggedarray->Set(thread, i, JSTaggedValue(i));
243         dstSemiTaggedarray->Set(thread, i, JSTaggedValue(-i));
244         dstOldTaggedarray->Set(thread, i, JSTaggedValue(-i));
245     }
246     TaggedArray::CopyTaggedArrayElement(thread, srcSemiTaggedarray, dstSemiTaggedarray, ELEMENT_NUMS);
247     TaggedArray::CopyTaggedArrayElement(thread, srcOldTaggedarray, dstOldTaggedarray, ELEMENT_NUMS);
248 
249     for (uint32_t i = 0; i < ELEMENT_NUMS; i++) {
250         EXPECT_EQ(srcSemiTaggedarray->Get(thread, i), dstSemiTaggedarray->Get(thread, i));
251         EXPECT_EQ(srcOldTaggedarray->Get(thread, i), dstOldTaggedarray->Get(thread, i));
252     }
253 }
254 }  // namespace panda::ecmascript
255