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