• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "common_components/heap/ark_collector/copy_barrier.h"
17 #include "common_components/heap/ark_collector/tests/mock_barrier_collector.h"
18 #include "common_components/mutator/mutator_manager.h"
19 #include "common_components/tests/test_helper.h"
20 #include "common_components/heap/heap_manager.h"
21 #include "common_interfaces/base_runtime.h"
22 
23 using namespace common;
24 
25 namespace common::test {
26 class CopyBarrierTest : public common::test::BaseTestWithScope {
27 protected:
SetUpTestCase()28     static void SetUpTestCase()
29     {
30         BaseRuntime::GetInstance()->Init();
31     }
32 
TearDownTestCase()33     static void TearDownTestCase() {}
34 
SetUp()35     void SetUp() override
36     {
37         MutatorManager::Instance().CreateRuntimeMutator(ThreadType::ARK_PROCESSOR);
38     }
39 
TearDown()40     void TearDown() override
41     {
42         MutatorManager::Instance().DestroyRuntimeMutator(ThreadType::ARK_PROCESSOR);
43     }
44 };
45 
HWTEST_F_L0(CopyBarrierTest,ReadRefField_TEST1)46 HWTEST_F_L0(CopyBarrierTest, ReadRefField_TEST1)
47 {
48     MockCollector collector;
49     auto copyBarrier = std::make_unique<CopyBarrier>(collector);
50     ASSERT_TRUE(copyBarrier != nullptr);
51 
52     HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
53     BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
54     RefField<false> field(obj);
55 
56     BaseObject* resultObj = copyBarrier->ReadRefField(obj, field);
57     ASSERT_TRUE(resultObj != nullptr);
58     EXPECT_EQ(resultObj, obj);
59 }
60 
HWTEST_F_L0(CopyBarrierTest,ReadRefField_TEST2)61 HWTEST_F_L0(CopyBarrierTest, ReadRefField_TEST2)
62 {
63     MockCollector collector;
64     auto copyBarrier = std::make_unique<CopyBarrier>(collector);
65     ASSERT_TRUE(copyBarrier != nullptr);
66 
67     HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
68     BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
69     RefField<false> field(obj);
70 
71     BaseObject* resultObj = copyBarrier->ReadRefField(nullptr, field);
72     ASSERT_TRUE(resultObj != nullptr);
73     EXPECT_EQ(resultObj, obj);
74 }
75 
HWTEST_F_L0(CopyBarrierTest,ReadRefField_TEST3)76 HWTEST_F_L0(CopyBarrierTest, ReadRefField_TEST3)
77 {
78     MockCollector collector;
79     auto copyBarrier = std::make_unique<CopyBarrier>(collector);
80     ASSERT_TRUE(copyBarrier != nullptr);
81 
82     HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
83     BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
84     RefField<false> field(obj, true);
85 
86     BaseObject* resultObj = copyBarrier->ReadRefField(obj, field);
87     ASSERT_TRUE(resultObj != nullptr);
88     constexpr uint64_t TAG_WEAK = 0x01ULL;
89     BaseObject* newObj = reinterpret_cast<BaseObject*>(reinterpret_cast<uintptr_t>(obj) | TAG_WEAK);
90     EXPECT_EQ(resultObj, newObj);
91 }
92 
HWTEST_F_L0(CopyBarrierTest,ReadRefField_TEST4)93 HWTEST_F_L0(CopyBarrierTest, ReadRefField_TEST4)
94 {
95     MockCollectorForwardTest collector;
96     auto copyBarrier = std::make_unique<CopyBarrier>(collector);
97     ASSERT_TRUE(copyBarrier != nullptr);
98 
99     HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
100     BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
101     RefField<false> field(nullptr);
102 
103     BaseObject* resultObj = copyBarrier->ReadRefField(obj, field);
104     ASSERT_TRUE(resultObj == nullptr);
105 }
106 
HWTEST_F_L0(CopyBarrierTest,ReadRefField_TEST5)107 HWTEST_F_L0(CopyBarrierTest, ReadRefField_TEST5)
108 {
109     MockCollectorForwardTest collector;
110     auto copyBarrier = std::make_unique<CopyBarrier>(collector);
111     ASSERT_TRUE(copyBarrier != nullptr);
112 
113     HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
114     BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
115     RefField<false> field(obj, true);
116 
117     BaseObject* resultObj = copyBarrier->ReadRefField(obj, field);
118     ASSERT_TRUE(resultObj != nullptr);
119 }
120 
HWTEST_F_L0(CopyBarrierTest,ReadStaticRef_TEST1)121 HWTEST_F_L0(CopyBarrierTest, ReadStaticRef_TEST1)
122 {
123     MockCollector collector;
124     auto copyBarrier = std::make_unique<CopyBarrier>(collector);
125     ASSERT_TRUE(copyBarrier != nullptr);
126 
127     HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
128     BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
129     RefField<false> field(obj);
130 
131     BaseObject* resultObj = copyBarrier->ReadStaticRef(field);
132     ASSERT_TRUE(resultObj != nullptr);
133     EXPECT_EQ(resultObj, obj);
134 }
135 
HWTEST_F_L0(CopyBarrierTest,ReadStringTableStaticRef_TEST1)136 HWTEST_F_L0(CopyBarrierTest, ReadStringTableStaticRef_TEST1)
137 {
138     MockCollector collector;
139     auto copyBarrier = std::make_unique<CopyBarrier>(collector);
140     ASSERT_TRUE(copyBarrier != nullptr);
141 
142     RefField<false> field(nullptr);
143 
144     BaseObject* resultObj = copyBarrier->ReadStringTableStaticRef(field);
145     ASSERT_TRUE(resultObj == nullptr);
146 }
147 
HWTEST_F_L0(CopyBarrierTest,ReadStringTableStaticRef_TEST2)148 HWTEST_F_L0(CopyBarrierTest, ReadStringTableStaticRef_TEST2)
149 {
150     MockCollector collector;
151     auto copyBarrier = std::make_unique<CopyBarrier>(collector);
152     ASSERT_TRUE(copyBarrier != nullptr);
153 
154     HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
155     BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
156     RegionDesc *regionInfo = RegionDesc::GetRegionDescAt(addr);
157     regionInfo->SetRegionAllocPtr(addr - 1);
158     regionInfo->SetMarkingLine();
159     RefField<false> field(obj);
160 
161     BaseObject* resultObj = copyBarrier->ReadStringTableStaticRef(field);
162     ASSERT_TRUE(resultObj != nullptr);
163 }
164 
HWTEST_F_L0(CopyBarrierTest,ReadStringTableStaticRef_TEST3)165 HWTEST_F_L0(CopyBarrierTest, ReadStringTableStaticRef_TEST3)
166 {
167     MockCollector collector;
168     auto copyBarrier = std::make_unique<CopyBarrier>(collector);
169     ASSERT_TRUE(copyBarrier != nullptr);
170 
171     HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
172     BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
173     RegionDesc *regionInfo = RegionDesc::GetRegionDescAt(addr);
174     regionInfo->SetRegionType(RegionDesc::RegionType::ALIVE_REGION_FIRST);
175     RefField<false> field(obj);
176 
177     BaseObject* resultObj = copyBarrier->ReadStringTableStaticRef(field);
178     ASSERT_TRUE(resultObj == nullptr);
179 }
180 
HWTEST_F_L0(CopyBarrierTest,ReadStringTableStaticRef_TEST4)181 HWTEST_F_L0(CopyBarrierTest, ReadStringTableStaticRef_TEST4)
182 {
183     MockCollector collector;
184     auto copyBarrier = std::make_unique<CopyBarrier>(collector);
185     ASSERT_TRUE(copyBarrier != nullptr);
186 
187     HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
188     BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
189     RefField<false> field(obj);
190 
191     Heap::GetHeap().SetGCReason(GC_REASON_YOUNG);
192     BaseObject* resultObj = copyBarrier->ReadStringTableStaticRef(field);
193     ASSERT_TRUE(resultObj != nullptr);
194 }
195 
HWTEST_F_L0(CopyBarrierTest,ReadStruct_TEST1)196 HWTEST_F_L0(CopyBarrierTest, ReadStruct_TEST1)
197 {
198     MockCollector collector;
199     auto copyBarrier = std::make_unique<CopyBarrier>(collector);
200     ASSERT_TRUE(copyBarrier != nullptr);
201 
202     HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
203     BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
204     HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
205     BaseObject* srcObj = reinterpret_cast<BaseObject*>(src);
206     srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING);
207 
208     constexpr size_t size = sizeof(BaseObject);
209     uint8_t dstBuffer[size] = {};
210     HeapAddress dst = reinterpret_cast<HeapAddress>(dstBuffer);
211     BaseObject* dstObj = reinterpret_cast<BaseObject*>(dst);
212     dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED);
213     EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding());
214 
215     copyBarrier->ReadStruct(dst, obj, src, size);
216     EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding());
217 }
218 
HWTEST_F_L0(CopyBarrierTest,ReadStruct_TEST2)219 HWTEST_F_L0(CopyBarrierTest, ReadStruct_TEST2)
220 {
221     MockCollector collector;
222     auto copyBarrier = std::make_unique<CopyBarrier>(collector);
223     ASSERT_TRUE(copyBarrier != nullptr);
224 
225     HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
226     BaseObject* srcObj = reinterpret_cast<BaseObject*>(src);
227     srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING);
228 
229     constexpr size_t size = sizeof(BaseObject);
230     uint8_t dstBuffer[size] = {};
231     HeapAddress dst = reinterpret_cast<HeapAddress>(dstBuffer);
232     BaseObject* dstObj = reinterpret_cast<BaseObject*>(dst);
233     dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED);
234     EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding());
235 
236     copyBarrier->ReadStruct(dst, nullptr, src, size);
237     EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding());
238 }
239 
HWTEST_F_L0(CopyBarrierTest,AtomicWriteRefField_TEST1)240 HWTEST_F_L0(CopyBarrierTest, AtomicWriteRefField_TEST1)
241 {
242     MockCollector collector;
243     auto copyBarrier = std::make_unique<CopyBarrier>(collector);
244     ASSERT_TRUE(copyBarrier != nullptr);
245 
246     HeapAddress oldAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
247     BaseObject* oldObj = reinterpret_cast<BaseObject*>(oldAddr);
248     constexpr size_t oldSize = 100;
249     oldObj->SetSizeForwarded(oldSize);
250     EXPECT_EQ(oldObj->GetSizeForwarded(), oldSize);
251     RefField<true> oldField(oldObj);
252     MAddress oldAddress = oldField.GetFieldValue();
253 
254     HeapAddress newAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
255     BaseObject* newObj = reinterpret_cast<BaseObject*>(newAddr);
256     constexpr size_t newSize = 200;
257     newObj->SetSizeForwarded(newSize);
258     EXPECT_EQ(newObj->GetSizeForwarded(), newSize);
259     RefField<true> newField(newObj);
260     MAddress neWAddress = newField.GetFieldValue();
261     EXPECT_NE(oldAddress, neWAddress);
262 
263     copyBarrier->AtomicWriteRefField(oldObj, oldField, newObj, std::memory_order_relaxed);
264     EXPECT_EQ(oldField.GetFieldValue(), neWAddress);
265 }
266 
HWTEST_F_L0(CopyBarrierTest,AtomicWriteRefField_TEST2)267 HWTEST_F_L0(CopyBarrierTest, AtomicWriteRefField_TEST2)
268 {
269     MockCollector collector;
270     auto copyBarrier = std::make_unique<CopyBarrier>(collector);
271     ASSERT_TRUE(copyBarrier != nullptr);
272 
273     HeapAddress oldAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
274     BaseObject* oldObj = reinterpret_cast<BaseObject*>(oldAddr);
275     constexpr size_t oldSize = 100;
276     oldObj->SetSizeForwarded(oldSize);
277     EXPECT_EQ(oldObj->GetSizeForwarded(), oldSize);
278     RefField<true> oldField(oldObj);
279     MAddress oldAddress = oldField.GetFieldValue();
280 
281     HeapAddress newAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
282     BaseObject* newObj = reinterpret_cast<BaseObject*>(newAddr);
283     constexpr size_t newSize = 200;
284     newObj->SetSizeForwarded(newSize);
285     EXPECT_EQ(newObj->GetSizeForwarded(), newSize);
286     RefField<true> newField(newObj);
287     MAddress neWAddress = newField.GetFieldValue();
288     EXPECT_NE(oldAddress, neWAddress);
289 
290     copyBarrier->AtomicWriteRefField(nullptr, oldField, newObj, std::memory_order_relaxed);
291     EXPECT_EQ(oldField.GetFieldValue(), neWAddress);
292 }
293 
HWTEST_F_L0(CopyBarrierTest,CompareAndSwapRefField_TEST1)294 HWTEST_F_L0(CopyBarrierTest, CompareAndSwapRefField_TEST1)
295 {
296     MockCollector collector;
297     auto copyBarrier = std::make_unique<CopyBarrier>(collector);
298     ASSERT_TRUE(copyBarrier != nullptr);
299 
300     HeapAddress oldAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
301     BaseObject* oldObj = reinterpret_cast<BaseObject*>(oldAddr);
302     constexpr size_t oldSize = 100;
303     oldObj->SetSizeForwarded(oldSize);
304     EXPECT_EQ(oldObj->GetSizeForwarded(), oldSize);
305     RefField<true> oldField(oldObj);
306     MAddress oldAddress = oldField.GetFieldValue();
307     HeapAddress newAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
308     BaseObject* newObj = reinterpret_cast<BaseObject*>(newAddr);
309     constexpr size_t newSize = 200;
310     newObj->SetSizeForwarded(newSize);
311     EXPECT_EQ(newObj->GetSizeForwarded(), newSize);
312     RefField<true> newField(newObj);
313     MAddress neWAddress = newField.GetFieldValue();
314     EXPECT_NE(oldAddress, neWAddress);
315     bool result = copyBarrier->CompareAndSwapRefField(oldObj, oldField, oldObj, newObj,
316         std::memory_order_seq_cst, std::memory_order_seq_cst);
317     ASSERT_TRUE(result);
318 }
319 
HWTEST_F_L0(CopyBarrierTest,CompareAndSwapRefField_TEST2)320 HWTEST_F_L0(CopyBarrierTest, CompareAndSwapRefField_TEST2)
321 {
322     MockCollector collector;
323     auto copyBarrier = std::make_unique<CopyBarrier>(collector);
324     ASSERT_TRUE(copyBarrier != nullptr);
325 
326     HeapAddress oldAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
327     BaseObject* oldObj = reinterpret_cast<BaseObject*>(oldAddr);
328     constexpr size_t oldSize = 100;
329     oldObj->SetSizeForwarded(oldSize);
330     EXPECT_EQ(oldObj->GetSizeForwarded(), oldSize);
331     RefField<true> oldField(oldObj);
332 
333     bool result = copyBarrier->CompareAndSwapRefField(oldObj, oldField, oldObj, oldObj,
334         std::memory_order_seq_cst, std::memory_order_seq_cst);
335     ASSERT_TRUE(result);
336 }
337 
HWTEST_F_L0(CopyBarrierTest,CompareAndSwapRefField_TEST3)338 HWTEST_F_L0(CopyBarrierTest, CompareAndSwapRefField_TEST3)
339 {
340     MockCollector collector;
341     auto copyBarrier = std::make_unique<CopyBarrier>(collector);
342     ASSERT_TRUE(copyBarrier != nullptr);
343 
344     HeapAddress oldAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
345     BaseObject* oldObj = reinterpret_cast<BaseObject*>(oldAddr);
346     constexpr size_t oldSize = 100;
347     oldObj->SetSizeForwarded(oldSize);
348     EXPECT_EQ(oldObj->GetSizeForwarded(), oldSize);
349     RefField<true> oldField(oldObj);
350     MAddress oldAddress = oldField.GetFieldValue();
351 
352     HeapAddress newAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
353     BaseObject* newObj = reinterpret_cast<BaseObject*>(newAddr);
354     constexpr size_t newSize = 200;
355     newObj->SetSizeForwarded(newSize);
356     EXPECT_EQ(newObj->GetSizeForwarded(), newSize);
357     RefField<true> newField(newObj);
358     MAddress neWAddress = newField.GetFieldValue();
359     EXPECT_NE(oldAddress, neWAddress);
360 
361     bool result = copyBarrier->CompareAndSwapRefField(oldObj, newField, oldObj, newObj,
362         std::memory_order_seq_cst, std::memory_order_seq_cst);
363     ASSERT_FALSE(result);
364 }
365 }  // namespace common::test
366