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