• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #include "ecmascript/js_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 BarrierTest : public BaseTestWithScope<true> {
24 };
25 
HWTEST_F_L0(BarrierTest,YoungToYoungBatchCopy)26 HWTEST_F_L0(BarrierTest, YoungToYoungBatchCopy)
27 {
28     ObjectFactory* factory = thread->GetEcmaVM()->GetFactory();
29     uint32_t arrayLength = 10;
30     JSHandle<TaggedArray> srcArray = factory->NewTaggedArray(arrayLength);
31     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
32     for (uint32_t i = 0; i < arrayLength; i++) {
33         JSHandle<JSFunction> newFun = factory->NewJSFunction(env);
34         srcArray->Set(thread, i, newFun);
35     }
36 
37     JSHandle<TaggedArray> dstArray = factory->NewTaggedArray(arrayLength);
38     std::set<uintptr_t> LocalToShareBeforeCopy;
39 
40     Region* dstRegion = Region::ObjectAddressToRange(dstArray.GetObject<TaggedArray>());
41     dstRegion->IterateAllLocalToShareBits([&LocalToShareBeforeCopy](void* mem) {
42         LocalToShareBeforeCopy.emplace(ToUintPtr(mem));
43         return true;
44     });
45 
46     JSTaggedValue* to = reinterpret_cast<JSTaggedValue*>(ToUintPtr(dstArray->GetData()));
47     JSTaggedValue* from = reinterpret_cast<JSTaggedValue*>(ToUintPtr(srcArray->GetData()));
48     Barriers::CopyObject<true, false>(thread, *dstArray, to, from, arrayLength);
49 
50     // young to young, all the bitset should not be changed.
51     dstRegion->IterateAllLocalToShareBits([&LocalToShareBeforeCopy](void* mem) {
52         EXPECT_TRUE(LocalToShareBeforeCopy.count(ToUintPtr(mem)));
53         return true;
54     });
55 
56     // check
57     for (uint32_t i = 0; i < arrayLength; i++) {
58         EXPECT_EQ(dstArray->Get(thread, i), srcArray->Get(thread, i));
59     }
60 }
61 
HWTEST_F_L0(BarrierTest,BatchCopyNoBarrier)62 HWTEST_F_L0(BarrierTest, BatchCopyNoBarrier)
63 {
64     ObjectFactory* factory = thread->GetEcmaVM()->GetFactory();
65     uint32_t arrayLength = 10;
66     JSHandle<TaggedArray> srcArray = factory->NewTaggedArray(arrayLength);
67     for (uint32_t i = 0; i < arrayLength; i++) {
68         srcArray->Set(thread, i, JSTaggedValue(i));
69     }
70 
71     JSHandle<TaggedArray> dstArray = factory->NewTaggedArray(arrayLength);
72     std::set<uintptr_t> LocalToShareBeforeCopy;
73 
74     Region* dstRegion = Region::ObjectAddressToRange(dstArray.GetObject<TaggedArray>());
75     dstRegion->IterateAllLocalToShareBits([&LocalToShareBeforeCopy](void* mem) {
76         LocalToShareBeforeCopy.emplace(ToUintPtr(mem));
77         return true;
78     });
79 
80     JSTaggedValue* to = reinterpret_cast<JSTaggedValue*>(ToUintPtr(dstArray->GetData()));
81     JSTaggedValue* from = reinterpret_cast<JSTaggedValue*>(ToUintPtr(srcArray->GetData()));
82     Barriers::CopyObjectPrimitive<false>(to, from, arrayLength);
83 
84     dstRegion->IterateAllLocalToShareBits([&LocalToShareBeforeCopy](void* mem) {
85         EXPECT_TRUE(LocalToShareBeforeCopy.count(ToUintPtr(mem)));
86         return true;
87     });
88 
89     // check
90     for (uint32_t i = 0; i < arrayLength; i++) {
91         EXPECT_EQ(dstArray->Get(thread, i), srcArray->Get(thread, i));
92     }
93 
94     JSHandle<TaggedArray> dstArray2 = factory->NewTaggedArray(arrayLength);
95     JSTaggedValue* to2 = reinterpret_cast<JSTaggedValue*>(ToUintPtr(dstArray2->GetData()));
96     JSTaggedValue* from2 = reinterpret_cast<JSTaggedValue*>(ToUintPtr(srcArray->GetData()));
97     // barrier should also work for no heap value
98     Barriers::CopyObject<true, false>(thread, *dstArray, to2, from2, arrayLength);
99     // check
100     for (uint32_t i = 0; i < arrayLength; i++) {
101         EXPECT_EQ(dstArray2->Get(thread, i), srcArray->Get(thread, i));
102     }
103 }
104 
HWTEST_F_L0(BarrierTest,LocalToShareBatchCopy)105 HWTEST_F_L0(BarrierTest, LocalToShareBatchCopy)
106 {
107     ObjectFactory* factory = thread->GetEcmaVM()->GetFactory();
108     uint32_t arrayLength = 10;
109     JSHandle<TaggedArray> srcArray = factory->NewTaggedArray(arrayLength);
110     for (uint32_t i = 0; i < arrayLength; i++) {
111         JSHandle<EcmaString> str = factory->NewFromStdString(std::to_string(i) + "_" + std::to_string(i));
112         // string longer than 1 will be in sweepable shared heap
113         srcArray->Set(thread, i, str);
114     }
115 
116     JSHandle<TaggedArray> dstArray = factory->NewTaggedArray(arrayLength);
117     std::set<uintptr_t> LocalToShareBeforeCopy;
118 
119     Region* dstRegion = Region::ObjectAddressToRange(dstArray.GetObject<TaggedArray>());
120     dstRegion->IterateAllLocalToShareBits([&LocalToShareBeforeCopy](void* mem) {
121         LocalToShareBeforeCopy.emplace(ToUintPtr(mem));
122         return true;
123     });
124 
125     JSTaggedValue* to = reinterpret_cast<JSTaggedValue*>(ToUintPtr(dstArray->GetData()));
126     JSTaggedValue* from = reinterpret_cast<JSTaggedValue*>(ToUintPtr(srcArray->GetData()));
127     Barriers::CopyObject<true, false>(thread, *dstArray, to, from, arrayLength);
128 
129     std::set<uintptr_t> LocalToShareSlot;
130     for (uint32_t i = 0; i < arrayLength; i++) {
131         LocalToShareSlot.insert(ToUintPtr(dstArray->GetData() + i));
132     }
133     // young to young, all the bitset should not be changed.
134     dstRegion->IterateAllLocalToShareBits([&LocalToShareSlot, &LocalToShareBeforeCopy, &dstArray, arrayLength](
135         void* mem) {
136             if (!LocalToShareBeforeCopy.count(ToUintPtr(mem))) {
137                 EXPECT_GE(ToUintPtr(mem), ToUintPtr(dstArray->GetData()));
138                 EXPECT_LT(ToUintPtr(mem), ToUintPtr(dstArray->GetData()+arrayLength));
139                 LocalToShareSlot.erase(ToUintPtr(mem));
140             } else {
141                 EXPECT_TRUE(LocalToShareBeforeCopy.count(ToUintPtr(mem)));
142             }
143             return true;
144         });
145     EXPECT_TRUE(LocalToShareSlot.empty());
146     // check
147     for (uint32_t i = 0; i < arrayLength; i++) {
148         EXPECT_EQ(dstArray->Get(thread, i), srcArray->Get(thread, i));
149     }
150 }
151 
HWTEST_F_L0(BarrierTest,LocalToReadOnlyShareBatchCopy)152 HWTEST_F_L0(BarrierTest, LocalToReadOnlyShareBatchCopy)
153 {
154     ObjectFactory* factory = thread->GetEcmaVM()->GetFactory();
155     uint32_t arrayLength = 10;
156     JSHandle<TaggedArray> srcArray = factory->NewTaggedArray(arrayLength);
157     for (uint32_t i = 0; i < arrayLength; i++) {
158         JSHandle<EcmaString> str = factory->NewFromStdString(std::to_string(i));
159         // One byte string is in readonly
160         srcArray->Set(thread, i, str);
161     }
162 
163     JSHandle<TaggedArray> dstArray = factory->NewTaggedArray(arrayLength);
164     std::set<uintptr_t> LocalToShareBeforeCopy;
165 
166     Region* dstRegion = Region::ObjectAddressToRange(dstArray.GetObject<TaggedArray>());
167     dstRegion->IterateAllLocalToShareBits([&LocalToShareBeforeCopy](void* mem) {
168         LocalToShareBeforeCopy.emplace(ToUintPtr(mem));
169         return true;
170     });
171 
172     JSTaggedValue* to = reinterpret_cast<JSTaggedValue*>(ToUintPtr(dstArray->GetData()));
173     JSTaggedValue* from = reinterpret_cast<JSTaggedValue*>(ToUintPtr(srcArray->GetData()));
174     Barriers::CopyObject<true, false>(thread, *dstArray, to, from, arrayLength);
175 
176     std::set<uintptr_t> LocalToShareSlot;
177     for (uint32_t i = 0; i < arrayLength; i++) {
178         LocalToShareSlot.insert(ToUintPtr(dstArray->GetData() + i));
179     }
180     // young to young, all the bitset should not be changed.
181     dstRegion->IterateAllLocalToShareBits([&LocalToShareSlot, &LocalToShareBeforeCopy](
182         void* mem) {
183             EXPECT_FALSE(LocalToShareSlot.count(ToUintPtr(mem)));
184             EXPECT_TRUE(LocalToShareBeforeCopy.count(ToUintPtr(mem)));
185             return true;
186         });
187     // check
188     for (uint32_t i = 0; i < arrayLength; i++) {
189         EXPECT_EQ(dstArray->Get(thread, i), srcArray->Get(thread, i));
190     }
191 }
192 
HWTEST_F_L0(BarrierTest,LocalToShareMixBatchCopy)193 HWTEST_F_L0(BarrierTest, LocalToShareMixBatchCopy)
194 {
195     ObjectFactory* factory = thread->GetEcmaVM()->GetFactory();
196     uint32_t arrayLength = 10;
197     JSHandle<TaggedArray> srcArray = factory->NewTaggedArray(arrayLength);
198     for (uint32_t i = 0; i < arrayLength; i++) {
199         if (i % 2 == 0) {
200             JSHandle<EcmaString> str = factory->NewFromStdString(std::to_string(i) + "_" + std::to_string(i));
201             // One byte string is in readonly
202             srcArray->Set(thread, i, str);
203         } else {
204             srcArray->Set(thread, i, JSTaggedValue(i));
205         }
206     }
207 
208     JSHandle<TaggedArray> dstArray = factory->NewTaggedArray(arrayLength);
209     std::set<uintptr_t> LocalToShareBeforeCopy;
210 
211     Region* dstRegion = Region::ObjectAddressToRange(dstArray.GetObject<TaggedArray>());
212     dstRegion->IterateAllLocalToShareBits([&LocalToShareBeforeCopy](void* mem) {
213         LocalToShareBeforeCopy.emplace(ToUintPtr(mem));
214         return true;
215     });
216 
217     JSTaggedValue* to = reinterpret_cast<JSTaggedValue*>(ToUintPtr(dstArray->GetData()));
218     JSTaggedValue* from = reinterpret_cast<JSTaggedValue*>(ToUintPtr(srcArray->GetData()));
219     Barriers::CopyObject<true, false>(thread, *dstArray, to, from, arrayLength);
220 
221     std::set<uintptr_t> LocalToShareSlot;
222     for (uint32_t i = 0; i < arrayLength; i++) {
223         if (i % 2 == 0) {
224             LocalToShareSlot.insert(ToUintPtr(dstArray->GetData() + i));
225         }
226     }
227     // young to young, all the bitset should not be changed.
228     dstRegion->IterateAllLocalToShareBits([&LocalToShareSlot, &LocalToShareBeforeCopy, &dstArray, arrayLength](
229         void* mem) {
230             if (!LocalToShareBeforeCopy.count(ToUintPtr(mem))) {
231                 EXPECT_GE(ToUintPtr(mem), ToUintPtr(dstArray->GetData()));
232                 EXPECT_LT(ToUintPtr(mem), ToUintPtr(dstArray->GetData()+arrayLength));
233                 LocalToShareSlot.erase(ToUintPtr(mem));
234             } else {
235                 EXPECT_TRUE(LocalToShareBeforeCopy.count(ToUintPtr(mem)));
236             }
237             return true;
238         });
239     EXPECT_TRUE(LocalToShareSlot.empty());
240     // check
241     for (uint32_t i = 0; i < arrayLength; i++) {
242         EXPECT_EQ(dstArray->Get(thread, i), srcArray->Get(thread, i));
243     }
244 }
245 
HWTEST_F_L0(BarrierTest,OldToNewBatchCopy)246 HWTEST_F_L0(BarrierTest, OldToNewBatchCopy)
247 {
248     ObjectFactory* factory = thread->GetEcmaVM()->GetFactory();
249     uint32_t arrayLength = 10;
250     // length 50 will be in old
251     JSHandle<TaggedArray> srcArray = factory->NewOldSpaceTaggedArray(arrayLength);
252     JSHandle<TaggedArray> dstArray = factory->NewOldSpaceTaggedArray(arrayLength);
253 
254     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
255     JSHandle<JSFunction> newFun = factory->NewJSFunction(env); // in young
256     for (uint32_t i = 0; i < 10; i++) {
257         srcArray->Set(thread, i, newFun);
258     }
259 
260     std::set<uintptr_t> OldToNewSlot;
261     for (uint32_t i = 0; i < arrayLength; i++) {
262         if (Region::ObjectAddressToRange(srcArray->Get(thread, i).GetTaggedObject())->InYoungSpace()) {
263             OldToNewSlot.insert(ToUintPtr(dstArray->GetData() + i));
264         }
265     }
266     EXPECT_TRUE(!OldToNewSlot.empty());
267 
268     std::set<uintptr_t> OldToNewBeforeCopy;
269     std::set<uintptr_t> LocalToShareBeforeCopy;
270 
271     Region* dstRegion = Region::ObjectAddressToRange(dstArray.GetObject<TaggedArray>());
272     dstRegion->IterateAllOldToNewBits([&OldToNewBeforeCopy](void* mem) {
273         OldToNewBeforeCopy.emplace(ToUintPtr(mem));
274         return true;
275     });
276     dstRegion->IterateAllLocalToShareBits([&LocalToShareBeforeCopy](void* mem) {
277         LocalToShareBeforeCopy.emplace(ToUintPtr(mem));
278         return true;
279     });
280 
281     JSTaggedValue* to = reinterpret_cast<JSTaggedValue*>(ToUintPtr(dstArray->GetData()));
282     JSTaggedValue* from = reinterpret_cast<JSTaggedValue*>(ToUintPtr(srcArray->GetData()));
283     Barriers::CopyObject<true, false>(thread, *dstArray, to, from, arrayLength);
284 
285     // young to young, all the bitset should not be changed.
286     dstRegion->IterateAllLocalToShareBits([&LocalToShareBeforeCopy](void* mem) {
287         EXPECT_TRUE(LocalToShareBeforeCopy.count(ToUintPtr(mem)));
288         return true;
289     });
290     // check
291     for (uint32_t i = 0; i < arrayLength; i++) {
292         EXPECT_EQ(dstArray->Get(thread, i), srcArray->Get(thread, i));
293     }
294 }
295 
HWTEST_F_L0(BarrierTest,LocalToShareUnshift)296 HWTEST_F_L0(BarrierTest, LocalToShareUnshift)
297 {
298     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
299     uint32_t arrayLength = 40;
300     JSHandle<TaggedArray> array = factory->NewTaggedArray(arrayLength);
301     for (uint32_t i = 0; i < arrayLength; i++) {
302         JSHandle<EcmaString> str = factory->NewFromStdString(std::to_string(i) + "_" + std::to_string(i));
303         // string longer than 1 will be in sweepable shared heap
304         array->Set(thread, i, str);
305     }
306     JSHandle<JSArray> jsArray = JSArray::CreateArrayFromList(thread, array);
307 
308     JSHandle<EcmaString> unshiftStr = factory->NewFromStdString("unshift");
309     auto unshiftFunc = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>(jsArray),
310                                                   JSHandle<JSTaggedValue>(unshiftStr)).GetValue();
311     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, unshiftFunc.GetTaggedValue(),
312                                                                     jsArray.GetTaggedValue(),
313                                                                     thread->GlobalConstants()->GetUndefined(), 1);
314     info->SetCallArg(thread->GlobalConstants()->GetUndefined());
315     EcmaInterpreter::Execute(info);
316 
317     array = JSHandle<TaggedArray>(thread, jsArray->GetElements());
318     Region *dstRegion = Region::ObjectAddressToRange(array.GetObject<TaggedArray>());
319     std::set<uintptr_t> LocalToShareSlot;
320     for (uint32_t i = 1; i < arrayLength + 1; i++) {
321         LocalToShareSlot.insert(ToUintPtr(array->GetData() + i));
322     }
323     dstRegion->IterateAllLocalToShareBits([&LocalToShareSlot](void *mem) {
324         LocalToShareSlot.erase(ToUintPtr(mem));
325         return true;
326     });
327 
328     EXPECT_TRUE(LocalToShareSlot.empty());
329 }
330 
HWTEST_F_L0(BarrierTest,UnshiftBarrierMoveForward)331 HWTEST_F_L0(BarrierTest, UnshiftBarrierMoveForward)
332 {
333     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
334     uint32_t arrayLength = 3;
335     JSHandle<TaggedArray> array = factory->NewTaggedArray(arrayLength);
336     for (uint32_t i = 0; i < arrayLength; i++) {
337         JSHandle<EcmaString> str = factory->NewFromStdString(std::to_string(i) + "_" + std::to_string(i));
338         // string longer than 1 will be in sweepable shared heap
339         array->Set(thread, i, str);
340     }
341     JSHandle<JSArray> jsArray = JSArray::CreateArrayFromList(thread, array);
342 
343     JSHandle<EcmaString> unshiftStr = factory->NewFromStdString("unshift");
344     auto unshiftFunc = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>(jsArray),
345                                                   JSHandle<JSTaggedValue>(unshiftStr)).GetValue();
346     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, unshiftFunc.GetTaggedValue(),
347                                                                     jsArray.GetTaggedValue(),
348                                                                     thread->GlobalConstants()->GetUndefined(), 3);
349     info->SetCallArg(thread->GlobalConstants()->GetUndefined(), thread->GlobalConstants()->GetUndefined(),
350                      thread->GlobalConstants()->GetUndefined());
351     EcmaInterpreter::Execute(info);
352 
353     array = JSHandle<TaggedArray>(thread, jsArray->GetElements());
354     Region *dstRegion = Region::ObjectAddressToRange(array.GetObject<TaggedArray>());
355     std::set<uintptr_t> LocalToShareSlot;
356     for (uint32_t i = 3; i < arrayLength + 3; i++) {
357         LocalToShareSlot.insert(ToUintPtr(array->GetData() + i));
358     }
359     dstRegion->IterateAllLocalToShareBits([&LocalToShareSlot](void *mem) {
360         LocalToShareSlot.erase(ToUintPtr(mem));
361         return true;
362     });
363 
364     EXPECT_TRUE(LocalToShareSlot.empty());
365 }
366 
HWTEST_F_L0(BarrierTest,UnshiftBarrierMoveBackward)367 HWTEST_F_L0(BarrierTest, UnshiftBarrierMoveBackward)
368 {
369     if (!thread->IsAsmInterpreter()) {
370         return;
371     }
372 #ifdef ENABLE_NEXT_OPTIMIZATION
373     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
374     uint32_t arrayLength = 20;
375     JSHandle<TaggedArray> array = factory->NewTaggedArray(arrayLength);
376     for (uint32_t i = 0; i < arrayLength; i++) {
377         if (i % 2 == 0) {
378             JSHandle<EcmaString> str = factory->NewFromStdString(std::to_string(i) + "_" + std::to_string(i));
379             // string longer than 1 will be in sweepable shared heap
380             array->Set(thread, i, str);
381             continue;
382         }
383         array->Set(thread, i, JSTaggedValue(1));
384     }
385     JSHandle<JSArray> jsArray = JSArray::CreateArrayFromList(thread, array);
386 
387     JSHandle<EcmaString> unshiftStr = factory->NewFromStdString("unshift");
388     auto unshiftFunc = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>(jsArray),
389                                                   JSHandle<JSTaggedValue>(unshiftStr)).GetValue();
390     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, unshiftFunc.GetTaggedValue(),
391                                                                     jsArray.GetTaggedValue(),
392                                                                     thread->GlobalConstants()->GetUndefined(), 1);
393     info->SetCallArg(thread->GlobalConstants()->GetUndefined());
394     EcmaInterpreter::Execute(info);
395 
396     array = JSHandle<TaggedArray>(thread, jsArray->GetElements());
397     Region *dstRegion = Region::ObjectAddressToRange(array.GetObject<TaggedArray>());
398     std::set<uintptr_t> LocalToShareSlot;
399     std::set<uintptr_t> LocalTaggedIntSlot;
400     for (uint32_t i = 1; i < arrayLength + 1; i++) {
401         if (i % 2 != 0) {
402             LocalToShareSlot.insert(ToUintPtr(array->GetData() + i));
403             continue;
404         }
405         LocalTaggedIntSlot.insert(ToUintPtr(array->GetData() + i));
406     }
407     dstRegion->IterateAllLocalToShareBits([&LocalToShareSlot, &LocalTaggedIntSlot](void *mem) {
408         EXPECT_FALSE(LocalTaggedIntSlot.count(ToUintPtr(mem)));
409         LocalToShareSlot.erase(ToUintPtr(mem));
410         return true;
411     });
412 
413     EXPECT_TRUE(LocalToShareSlot.empty());
414 #endif
415 }
416 
HWTEST_F_L0(BarrierTest,UnshiftBarrierMoveForward1)417 HWTEST_F_L0(BarrierTest, UnshiftBarrierMoveForward1)
418 {
419     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
420     uint32_t arrayLength = 3;
421     JSHandle<TaggedArray> array = factory->NewTaggedArray(arrayLength);
422     for (uint32_t i = 0; i < arrayLength; i++) {
423         if (i % 2 != 0) {
424             JSHandle<EcmaString> str = factory->NewFromStdString(std::to_string(i) + "_" + std::to_string(i));
425             // string longer than 1 will be in sweepable shared heap
426             array->Set(thread, i, str);
427             continue;
428         }
429         array->Set(thread, i, JSTaggedValue(1));
430     }
431     JSHandle<JSArray> jsArray = JSArray::CreateArrayFromList(thread, array);
432 
433     JSHandle<EcmaString> unshiftStr = factory->NewFromStdString("unshift");
434     auto unshiftFunc = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>(jsArray),
435                                                   JSHandle<JSTaggedValue>(unshiftStr)).GetValue();
436     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, unshiftFunc.GetTaggedValue(),
437                                                                     jsArray.GetTaggedValue(),
438                                                                     thread->GlobalConstants()->GetUndefined(), 3);
439     info->SetCallArg(thread->GlobalConstants()->GetUndefined(), thread->GlobalConstants()->GetUndefined(),
440                      thread->GlobalConstants()->GetUndefined());
441     EcmaInterpreter::Execute(info);
442 
443     array = JSHandle<TaggedArray>(thread, jsArray->GetElements());
444     Region *dstRegion = Region::ObjectAddressToRange(array.GetObject<TaggedArray>());
445     std::set<uintptr_t> LocalToShareSlot;
446     std::set<uintptr_t> LocalTaggedIntSlot;
447     for (uint32_t i = 3; i < arrayLength + 3; i++) {
448         if (i % 2 == 0) {
449             LocalToShareSlot.insert(ToUintPtr(array->GetData() + i));
450             continue;
451         }
452         LocalTaggedIntSlot.insert(ToUintPtr(array->GetData() + i));
453     }
454     dstRegion->IterateAllLocalToShareBits([&LocalToShareSlot, &LocalTaggedIntSlot](void *mem) {
455         EXPECT_FALSE(LocalTaggedIntSlot.count(ToUintPtr(mem)));
456         LocalToShareSlot.erase(ToUintPtr(mem));
457         return true;
458     });
459 
460     EXPECT_TRUE(LocalToShareSlot.empty());
461 }
462 
HWTEST_F_L0(BarrierTest,SliceBarrierMove)463 HWTEST_F_L0(BarrierTest, SliceBarrierMove)
464 {
465     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
466     uint32_t arrayLength = 20;
467     JSHandle<TaggedArray> array = factory->NewTaggedArray(arrayLength);
468     for (uint32_t i = 0; i < arrayLength; i++) {
469         if (i % 2 == 0) {
470             JSHandle<EcmaString> str = factory->NewFromStdString(std::to_string(i) + "_" + std::to_string(i));
471             // string longer than 1 will be in sweepable shared heap
472             array->Set(thread, i, str);
473             continue;
474         }
475         array->Set(thread, i, JSTaggedValue(1));
476     }
477     JSHandle<JSArray> jsArray = JSArray::CreateArrayFromList(thread, array);
478 
479     JSHandle<EcmaString> sliceStr = factory->NewFromStdString("slice");
480     auto unshiftFunc = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>(jsArray),
481                                                   JSHandle<JSTaggedValue>(sliceStr)).GetValue();
482     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, unshiftFunc.GetTaggedValue(),
483                                                                     jsArray.GetTaggedValue(),
484                                                                     thread->GlobalConstants()->GetUndefined(), 1);
485     info->SetCallArg(JSTaggedValue(10));
486     JSTaggedValue result = EcmaInterpreter::Execute(info);
487     JSArray *resultArray = JSArray::Cast(result.GetTaggedObject());
488     array = JSHandle<TaggedArray>(thread, resultArray->GetElements());
489     Region *dstRegion = Region::ObjectAddressToRange(array.GetObject<TaggedArray>());
490     std::set<uintptr_t> LocalToShareSlot;
491     std::set<uintptr_t> LocalTaggedIntSlot;
492     for (uint32_t i = 0; i < 10; i++) {
493         if (i % 2 == 0) {
494             LocalToShareSlot.insert(ToUintPtr(array->GetData() + i));
495             continue;
496         }
497         LocalTaggedIntSlot.insert(ToUintPtr(array->GetData() + i));
498     }
499     dstRegion->IterateAllLocalToShareBits([&LocalToShareSlot, &LocalTaggedIntSlot](void *mem) {
500         EXPECT_FALSE(LocalTaggedIntSlot.count(ToUintPtr(mem)));
501         LocalToShareSlot.erase(ToUintPtr(mem));
502         return true;
503     });
504 
505     EXPECT_TRUE(LocalToShareSlot.empty());
506 }
507 
HWTEST_F_L0(BarrierTest,LocalToShareReverse)508 HWTEST_F_L0(BarrierTest, LocalToShareReverse)
509 {
510     if (!thread->IsAsmInterpreter()) {
511         return;
512     }
513 #ifdef ENABLE_NEXT_OPTIMIZATION
514     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
515     uint32_t arrayLength = 40;
516     JSHandle<TaggedArray> array = factory->NewTaggedArray(arrayLength);
517     for (uint32_t i = 0; i < arrayLength; i++) {
518         if (i % 2 == 0) {
519             JSHandle<EcmaString> str = factory->NewFromStdString(std::to_string(i) + "_" + std::to_string(i));
520             array->Set(thread, i, str);
521         } else {
522             array->Set(thread, i, JSTaggedValue(i));
523         }
524     }
525     JSHandle<JSArray> jsArray = JSArray::CreateArrayFromList(thread, array);
526 
527     JSHandle<EcmaString> reverseStr = factory->NewFromStdString("reverse");
528     auto reverseFunc = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>(jsArray),
529                                                   JSHandle<JSTaggedValue>(reverseStr)).GetValue();
530     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, reverseFunc.GetTaggedValue(),
531                                                                     jsArray.GetTaggedValue(),
532                                                                     thread->GlobalConstants()->GetUndefined(), 0);
533     EcmaInterpreter::Execute(info);
534 
535     array = JSHandle<TaggedArray>(thread, jsArray->GetElements());
536     Region *dstRegion = Region::ObjectAddressToRange(array.GetObject<TaggedArray>());
537     std::set<uintptr_t> LocalToShareSlot1;
538     std::set<uintptr_t> LocalToShareSlot2;
539     for (uint32_t i = 0; i < arrayLength; i++) {
540         if (i % 2 == 1) {
541             LocalToShareSlot1.insert(ToUintPtr(array->GetData() + i));
542         } else {
543             LocalToShareSlot2.insert(ToUintPtr(array->GetData() + i));
544         }
545     }
546     dstRegion->IterateAllLocalToShareBits([&LocalToShareSlot1, &LocalToShareSlot2](void *mem) {
547         LocalToShareSlot1.erase(ToUintPtr(mem));
548         LocalToShareSlot2.erase(ToUintPtr(mem));
549         return true;
550     });
551     EXPECT_TRUE(LocalToShareSlot1.empty());
552     EXPECT_EQ(LocalToShareSlot2.size(), arrayLength / 2);
553 #endif
554 }
555 
556 } // namespace panda::ecmascript
557