• 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/preforward_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 PreforwardBarrierTest : public 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(PreforwardBarrierTest,ReadRefField_TEST1)46 HWTEST_F_L0(PreforwardBarrierTest, ReadRefField_TEST1)
47 {
48     MockCollector collector;
49     auto preforwardBarrier = std::make_unique<PreforwardBarrier>(collector);
50     ASSERT_TRUE(preforwardBarrier != 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 = preforwardBarrier->ReadRefField(obj, field);
57     ASSERT_TRUE(resultObj != nullptr);
58     EXPECT_EQ(resultObj, obj);
59 }
60 
HWTEST_F_L0(PreforwardBarrierTest,ReadRefField_TEST2)61 HWTEST_F_L0(PreforwardBarrierTest, ReadRefField_TEST2)
62 {
63     MockCollector collector;
64     auto preforwardBarrier = std::make_unique<PreforwardBarrier>(collector);
65     ASSERT_TRUE(preforwardBarrier != 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 = preforwardBarrier->ReadRefField(nullptr, field);
72     ASSERT_TRUE(resultObj != nullptr);
73     EXPECT_EQ(resultObj, obj);
74 }
75 
HWTEST_F_L0(PreforwardBarrierTest,ReadRefField_TEST3)76 HWTEST_F_L0(PreforwardBarrierTest, ReadRefField_TEST3)
77 {
78     MockCollector collector;
79     auto preforwardBarrier = std::make_unique<PreforwardBarrier>(collector);
80     ASSERT_TRUE(preforwardBarrier != 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 = preforwardBarrier->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(PreforwardBarrierTest,ReadRefField_TEST4)93 HWTEST_F_L0(PreforwardBarrierTest, ReadRefField_TEST4)
94 {
95     MockCollectorForwardTest collector;
96     auto preforwardBarrier = std::make_unique<PreforwardBarrier>(collector);
97     ASSERT_TRUE(preforwardBarrier != 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 = preforwardBarrier->ReadRefField(obj, field);
104     ASSERT_TRUE(resultObj == nullptr);
105 }
106 
HWTEST_F_L0(PreforwardBarrierTest,ReadRefField_TEST5)107 HWTEST_F_L0(PreforwardBarrierTest, ReadRefField_TEST5)
108 {
109     MockCollectorForwardTest collector;
110     auto preforwardBarrier = std::make_unique<PreforwardBarrier>(collector);
111     ASSERT_TRUE(preforwardBarrier != 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 = preforwardBarrier->ReadRefField(obj, field);
118     ASSERT_TRUE(resultObj != nullptr);
119 }
120 
HWTEST_F_L0(PreforwardBarrierTest,ReadStaticRef_TEST1)121 HWTEST_F_L0(PreforwardBarrierTest, ReadStaticRef_TEST1)
122 {
123     MockCollector collector;
124     auto preforwardBarrier = std::make_unique<PreforwardBarrier>(collector);
125     ASSERT_TRUE(preforwardBarrier != 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 = preforwardBarrier->ReadStaticRef(field);
132     ASSERT_TRUE(resultObj != nullptr);
133     EXPECT_EQ(resultObj, obj);
134 }
135 
HWTEST_F_L0(PreforwardBarrierTest,ReadStringTableStaticRef_TEST1)136 HWTEST_F_L0(PreforwardBarrierTest, ReadStringTableStaticRef_TEST1)
137 {
138     MockCollector collector;
139     auto preforwardBarrier = std::make_unique<PreforwardBarrier>(collector);
140     ASSERT_TRUE(preforwardBarrier != nullptr);
141 
142     RefField<false> field(nullptr);
143 
144     BaseObject* resultObj = preforwardBarrier->ReadStringTableStaticRef(field);
145     ASSERT_TRUE(resultObj == nullptr);
146 }
147 
HWTEST_F_L0(PreforwardBarrierTest,ReadStringTableStaticRef_TEST2)148 HWTEST_F_L0(PreforwardBarrierTest, ReadStringTableStaticRef_TEST2)
149 {
150     MockCollector collector;
151     auto preforwardBarrier = std::make_unique<PreforwardBarrier>(collector);
152     ASSERT_TRUE(preforwardBarrier != 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 = preforwardBarrier->ReadStringTableStaticRef(field);
162     ASSERT_TRUE(resultObj != nullptr);
163 }
164 
HWTEST_F_L0(PreforwardBarrierTest,ReadStringTableStaticRef_TEST3)165 HWTEST_F_L0(PreforwardBarrierTest, ReadStringTableStaticRef_TEST3)
166 {
167     MockCollector collector;
168     auto preforwardBarrier = std::make_unique<PreforwardBarrier>(collector);
169     ASSERT_TRUE(preforwardBarrier != 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 = preforwardBarrier->ReadStringTableStaticRef(field);
178     ASSERT_TRUE(resultObj == nullptr);
179 }
180 
HWTEST_F_L0(PreforwardBarrierTest,ReadStringTableStaticRef_TEST4)181 HWTEST_F_L0(PreforwardBarrierTest, ReadStringTableStaticRef_TEST4)
182 {
183     MockCollector collector;
184     auto preforwardBarrier = std::make_unique<PreforwardBarrier>(collector);
185     ASSERT_TRUE(preforwardBarrier != 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 = preforwardBarrier->ReadStringTableStaticRef(field);
193     ASSERT_TRUE(resultObj != nullptr);
194 }
195 
HWTEST_F_L0(PreforwardBarrierTest,ReadStruct_TEST1)196 HWTEST_F_L0(PreforwardBarrierTest, ReadStruct_TEST1)
197 {
198     MockCollector collector;
199     auto preforwardBarrier = std::make_unique<PreforwardBarrier>(collector);
200     ASSERT_TRUE(preforwardBarrier != 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     HeapAddress dst = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
208     BaseObject* dstObj = reinterpret_cast<BaseObject*>(dst);
209     dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED);
210     EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding());
211     preforwardBarrier->ReadStruct(dst, obj, src, sizeof(BaseObject));
212     EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding());
213 }
214 
HWTEST_F_L0(PreforwardBarrierTest,ReadStruct_TEST2)215 HWTEST_F_L0(PreforwardBarrierTest, ReadStruct_TEST2)
216 {
217     MockCollector collector;
218     auto preforwardBarrier = std::make_unique<PreforwardBarrier>(collector);
219     ASSERT_TRUE(preforwardBarrier != nullptr);
220 
221     HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
222     BaseObject* srcObj = reinterpret_cast<BaseObject*>(src);
223     srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING);
224     HeapAddress dst = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
225     BaseObject* dstObj = reinterpret_cast<BaseObject*>(dst);
226     dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED);
227     EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding());
228     preforwardBarrier->ReadStruct(dst, nullptr, src, sizeof(BaseObject));
229     EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding());
230 }
231 
HWTEST_F_L0(PreforwardBarrierTest,AtomicReadRefField_TEST1)232 HWTEST_F_L0(PreforwardBarrierTest, AtomicReadRefField_TEST1)
233 {
234     MockCollector collector;
235     auto preforwardBarrier = std::make_unique<PreforwardBarrier>(collector);
236     ASSERT_TRUE(preforwardBarrier != nullptr);
237 
238     HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
239     BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
240     constexpr size_t size = 100;
241     obj->SetSizeForwarded(size);
242     EXPECT_EQ(obj->GetSizeForwarded(), size);
243     RefField<true> field(obj);
244 
245     BaseObject* resultObj = nullptr;
246     resultObj = preforwardBarrier->AtomicReadRefField(obj, field, std::memory_order_seq_cst);
247     ASSERT_TRUE(resultObj != nullptr);
248 }
249 
HWTEST_F_L0(PreforwardBarrierTest,AtomicWriteRefField_TEST1)250 HWTEST_F_L0(PreforwardBarrierTest, AtomicWriteRefField_TEST1)
251 {
252     MockCollector collector;
253     auto preforwardBarrier = std::make_unique<PreforwardBarrier>(collector);
254     ASSERT_TRUE(preforwardBarrier != nullptr);
255 
256     HeapAddress oldAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
257     BaseObject* oldObj = reinterpret_cast<BaseObject*>(oldAddr);
258     constexpr size_t oldSize = 100;
259     oldObj->SetSizeForwarded(oldSize);
260     EXPECT_EQ(oldObj->GetSizeForwarded(), oldSize);
261     RefField<true> oldField(oldObj);
262     MAddress oldAddress = oldField.GetFieldValue();
263 
264     HeapAddress newAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
265     BaseObject* newObj = reinterpret_cast<BaseObject*>(newAddr);
266     constexpr size_t newSize = 200;
267     newObj->SetSizeForwarded(newSize);
268     EXPECT_EQ(newObj->GetSizeForwarded(), newSize);
269     RefField<true> newField(newObj);
270     MAddress neWAddress = newField.GetFieldValue();
271     EXPECT_NE(oldAddress, neWAddress);
272 
273     preforwardBarrier->AtomicWriteRefField(oldObj, oldField, newObj, std::memory_order_relaxed);
274     EXPECT_EQ(oldField.GetFieldValue(), neWAddress);
275 }
276 
HWTEST_F_L0(PreforwardBarrierTest,AtomicWriteRefField_TEST2)277 HWTEST_F_L0(PreforwardBarrierTest, AtomicWriteRefField_TEST2)
278 {
279     MockCollector collector;
280     auto preforwardBarrier = std::make_unique<PreforwardBarrier>(collector);
281     ASSERT_TRUE(preforwardBarrier != nullptr);
282 
283     HeapAddress oldAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
284     BaseObject* oldObj = reinterpret_cast<BaseObject*>(oldAddr);
285     constexpr size_t oldSize = 100;
286     oldObj->SetSizeForwarded(oldSize);
287     EXPECT_EQ(oldObj->GetSizeForwarded(), oldSize);
288     RefField<true> oldField(oldObj);
289     MAddress oldAddress = oldField.GetFieldValue();
290 
291     HeapAddress newAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
292     BaseObject* newObj = reinterpret_cast<BaseObject*>(newAddr);
293     constexpr size_t newSize = 200;
294     newObj->SetSizeForwarded(newSize);
295     EXPECT_EQ(newObj->GetSizeForwarded(), newSize);
296     RefField<true> newField(newObj);
297     MAddress neWAddress = newField.GetFieldValue();
298     EXPECT_NE(oldAddress, neWAddress);
299 
300     preforwardBarrier->AtomicWriteRefField(nullptr, oldField, newObj, std::memory_order_relaxed);
301     EXPECT_EQ(oldField.GetFieldValue(), neWAddress);
302 }
303 
HWTEST_F_L0(PreforwardBarrierTest,CompareAndSwapRefField_TEST1)304 HWTEST_F_L0(PreforwardBarrierTest, CompareAndSwapRefField_TEST1)
305 {
306     MockCollector collector;
307     auto preforwardBarrier = std::make_unique<PreforwardBarrier>(collector);
308     ASSERT_TRUE(preforwardBarrier != nullptr);
309 
310     HeapAddress oldAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
311     BaseObject* oldObj = reinterpret_cast<BaseObject*>(oldAddr);
312     constexpr size_t oldSize = 100;
313     oldObj->SetSizeForwarded(oldSize);
314     EXPECT_EQ(oldObj->GetSizeForwarded(), oldSize);
315     RefField<true> oldField(oldObj);
316     MAddress oldAddress = oldField.GetFieldValue();
317     HeapAddress newAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
318     BaseObject* newObj = reinterpret_cast<BaseObject*>(newAddr);
319     constexpr size_t newSize = 200;
320     newObj->SetSizeForwarded(newSize);
321     EXPECT_EQ(newObj->GetSizeForwarded(), newSize);
322     RefField<true> newField(newObj);
323     MAddress neWAddress = newField.GetFieldValue();
324     EXPECT_NE(oldAddress, neWAddress);
325     bool result = preforwardBarrier->CompareAndSwapRefField(oldObj, oldField, oldObj, newObj,
326         std::memory_order_seq_cst, std::memory_order_seq_cst);
327     ASSERT_TRUE(result);
328 }
329 
HWTEST_F_L0(PreforwardBarrierTest,CompareAndSwapRefField_TEST2)330 HWTEST_F_L0(PreforwardBarrierTest, CompareAndSwapRefField_TEST2)
331 {
332     MockCollector collector;
333     auto preforwardBarrier = std::make_unique<PreforwardBarrier>(collector);
334     ASSERT_TRUE(preforwardBarrier != nullptr);
335 
336     HeapAddress oldAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
337     BaseObject* oldObj = reinterpret_cast<BaseObject*>(oldAddr);
338     constexpr size_t oldSize = 100;
339     oldObj->SetSizeForwarded(oldSize);
340     EXPECT_EQ(oldObj->GetSizeForwarded(), oldSize);
341     RefField<true> oldField(oldObj);
342 
343     bool result = preforwardBarrier->CompareAndSwapRefField(oldObj, oldField, oldObj, oldObj,
344         std::memory_order_seq_cst, std::memory_order_seq_cst);
345     ASSERT_TRUE(result);
346 }
347 
HWTEST_F_L0(PreforwardBarrierTest,CompareAndSwapRefField_TEST3)348 HWTEST_F_L0(PreforwardBarrierTest, CompareAndSwapRefField_TEST3)
349 {
350     MockCollector collector;
351     auto preforwardBarrier = std::make_unique<PreforwardBarrier>(collector);
352     ASSERT_TRUE(preforwardBarrier != nullptr);
353 
354     HeapAddress oldAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
355     BaseObject* oldObj = reinterpret_cast<BaseObject*>(oldAddr);
356     constexpr size_t oldSize = 100;
357     oldObj->SetSizeForwarded(oldSize);
358     EXPECT_EQ(oldObj->GetSizeForwarded(), oldSize);
359     RefField<true> oldField(oldObj);
360     MAddress oldAddress = oldField.GetFieldValue();
361 
362     HeapAddress newAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
363     BaseObject* newObj = reinterpret_cast<BaseObject*>(newAddr);
364     constexpr size_t newSize = 200;
365     newObj->SetSizeForwarded(newSize);
366     EXPECT_EQ(newObj->GetSizeForwarded(), newSize);
367     RefField<true> newField(newObj);
368     MAddress neWAddress = newField.GetFieldValue();
369     EXPECT_NE(oldAddress, neWAddress);
370 
371     bool result = preforwardBarrier->CompareAndSwapRefField(oldObj, newField, oldObj, newObj,
372         std::memory_order_seq_cst, std::memory_order_seq_cst);
373     ASSERT_FALSE(result);
374 }
375 }  // namespace common::test
376