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/idle_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 IdleBarrierTest : 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(IdleBarrierTest,ReadStruct_TEST0)46 HWTEST_F_L0(IdleBarrierTest, ReadStruct_TEST0)
47 {
48 MockCollector collector;
49 auto idleBarrier = std::make_unique<IdleBarrier>(collector);
50 ASSERT_TRUE(idleBarrier != nullptr);
51
52 HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
53 BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
54 HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
55 BaseObject* srcObj = reinterpret_cast<BaseObject*>(src);
56 srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING);
57 HeapAddress dst = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
58 BaseObject* dstObj = reinterpret_cast<BaseObject*>(dst);
59 dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED);
60 EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding());
61 idleBarrier->ReadStruct(dst, obj, src, sizeof(BaseObject));
62 EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding());
63 }
64
HWTEST_F_L0(IdleBarrierTest,AtomicWriteRefField_TEST0)65 HWTEST_F_L0(IdleBarrierTest, AtomicWriteRefField_TEST0)
66 {
67 MockCollector collector;
68 auto idleBarrier = std::make_unique<IdleBarrier>(collector);
69 ASSERT_TRUE(idleBarrier != nullptr);
70
71 HeapAddress oldAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
72 BaseObject* oldObj = reinterpret_cast<BaseObject*>(oldAddr);
73 constexpr size_t oldSize = 100;
74 oldObj->SetSizeForwarded(oldSize);
75 EXPECT_EQ(oldObj->GetSizeForwarded(), oldSize);
76 RefField<true> oldField(oldObj);
77 MAddress oldAddress = oldField.GetFieldValue();
78
79 HeapAddress newAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
80 BaseObject* newObj = reinterpret_cast<BaseObject*>(newAddr);
81 constexpr size_t newSize = 200;
82 newObj->SetSizeForwarded(newSize);
83 EXPECT_EQ(newObj->GetSizeForwarded(), newSize);
84 RefField<true> newField(newObj);
85 MAddress neWAddress = newField.GetFieldValue();
86 EXPECT_NE(oldAddress, neWAddress);
87
88 idleBarrier->AtomicWriteRefField(oldObj, oldField, newObj, std::memory_order_relaxed);
89 EXPECT_EQ(oldField.GetFieldValue(), neWAddress);
90 }
91
HWTEST_F_L0(IdleBarrierTest,AtomicWriteRefField_TEST1)92 HWTEST_F_L0(IdleBarrierTest, AtomicWriteRefField_TEST1)
93 {
94 MockCollector collector;
95 auto idleBarrier = std::make_unique<IdleBarrier>(collector);
96 ASSERT_TRUE(idleBarrier != nullptr);
97
98 HeapAddress oldAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
99 BaseObject* oldObj = reinterpret_cast<BaseObject*>(oldAddr);
100 constexpr size_t oldSize = 100;
101 oldObj->SetSizeForwarded(oldSize);
102 EXPECT_EQ(oldObj->GetSizeForwarded(), oldSize);
103 RefField<true> oldField(oldObj);
104 MAddress oldAddress = oldField.GetFieldValue();
105
106 HeapAddress newAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
107 BaseObject* newObj = reinterpret_cast<BaseObject*>(newAddr);
108 constexpr size_t newSize = 200;
109 newObj->SetSizeForwarded(newSize);
110 EXPECT_EQ(newObj->GetSizeForwarded(), newSize);
111 RefField<true> newField(newObj);
112 MAddress neWAddress = newField.GetFieldValue();
113 EXPECT_NE(oldAddress, neWAddress);
114
115 idleBarrier->AtomicWriteRefField(nullptr, oldField, newObj, std::memory_order_relaxed);
116 EXPECT_EQ(oldField.GetFieldValue(), neWAddress);
117 }
118
HWTEST_F_L0(IdleBarrierTest,AtomicSwapRefField_TEST0)119 HWTEST_F_L0(IdleBarrierTest, AtomicSwapRefField_TEST0)
120 {
121 MockCollector collector;
122 auto idleBarrier = std::make_unique<IdleBarrier>(collector);
123 ASSERT_TRUE(idleBarrier != nullptr);
124
125 HeapAddress oldAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
126 BaseObject* oldObj = reinterpret_cast<BaseObject*>(oldAddr);
127 constexpr size_t oldSize = 100;
128 oldObj->SetSizeForwarded(oldSize);
129 EXPECT_EQ(oldObj->GetSizeForwarded(), oldSize);
130 RefField<true> oldField(oldObj);
131 MAddress oldAddress = oldField.GetFieldValue();
132
133 HeapAddress newAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
134 BaseObject* newObj = reinterpret_cast<BaseObject*>(newAddr);
135 constexpr size_t newSize = 200;
136 newObj->SetSizeForwarded(newSize);
137 EXPECT_EQ(newObj->GetSizeForwarded(), newSize);
138 RefField<true> newField(newObj);
139 MAddress neWAddress = newField.GetFieldValue();
140 EXPECT_NE(oldAddress, neWAddress);
141
142 BaseObject *retObj = idleBarrier->AtomicSwapRefField(oldObj, oldField, newObj, std::memory_order_relaxed);
143 ASSERT_TRUE(retObj != nullptr);
144 EXPECT_EQ(oldField.GetFieldValue(), newField.GetFieldValue());
145 }
146
HWTEST_F_L0(IdleBarrierTest,CompareAndSwapRefField_TEST1)147 HWTEST_F_L0(IdleBarrierTest, CompareAndSwapRefField_TEST1)
148 {
149 MockCollector collector;
150 auto idleBarrier = std::make_unique<IdleBarrier>(collector);
151 ASSERT_TRUE(idleBarrier != nullptr);
152
153 HeapAddress oldAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
154 BaseObject* oldObj = reinterpret_cast<BaseObject*>(oldAddr);
155 constexpr size_t oldSize = 100;
156 oldObj->SetSizeForwarded(oldSize);
157 EXPECT_EQ(oldObj->GetSizeForwarded(), oldSize);
158 RefField<true> oldField(oldObj);
159
160 bool result = idleBarrier->CompareAndSwapRefField(oldObj, oldField, oldObj, oldObj,
161 std::memory_order_seq_cst, std::memory_order_seq_cst);
162 ASSERT_TRUE(result);
163 }
164
HWTEST_F_L0(IdleBarrierTest,CompareAndSwapRefField_TEST2)165 HWTEST_F_L0(IdleBarrierTest, CompareAndSwapRefField_TEST2)
166 {
167 MockCollector collector;
168 auto idleBarrier = std::make_unique<IdleBarrier>(collector);
169 ASSERT_TRUE(idleBarrier != nullptr);
170
171 HeapAddress oldAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
172 BaseObject* oldObj = reinterpret_cast<BaseObject*>(oldAddr);
173 constexpr size_t oldSize = 100;
174 oldObj->SetSizeForwarded(oldSize);
175 EXPECT_EQ(oldObj->GetSizeForwarded(), oldSize);
176 RefField<true> oldField(oldObj);
177 MAddress oldAddress = oldField.GetFieldValue();
178
179 HeapAddress newAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
180 BaseObject* newObj = reinterpret_cast<BaseObject*>(newAddr);
181 constexpr size_t newSize = 200;
182 newObj->SetSizeForwarded(newSize);
183 EXPECT_EQ(newObj->GetSizeForwarded(), newSize);
184 RefField<true> newField(newObj);
185 MAddress neWAddress = newField.GetFieldValue();
186 EXPECT_NE(oldAddress, neWAddress);
187
188 bool result = idleBarrier->CompareAndSwapRefField(oldObj, newField, oldObj, newObj,
189 std::memory_order_seq_cst, std::memory_order_seq_cst);
190 ASSERT_FALSE(result);
191 }
192
HWTEST_F_L0(IdleBarrierTest,WriteRefField_TEST0)193 HWTEST_F_L0(IdleBarrierTest, WriteRefField_TEST0)
194 {
195 MockCollector collector;
196 auto idleBarrier = std::make_unique<IdleBarrier>(collector);
197 ASSERT_TRUE(idleBarrier != nullptr);
198
199 HeapAddress oldAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
200 BaseObject* oldObj = reinterpret_cast<BaseObject*>(oldAddr);
201 constexpr size_t oldSize = 100;
202 oldObj->SetSizeForwarded(oldSize);
203 EXPECT_EQ(oldObj->GetSizeForwarded(), oldSize);
204 RefField<false> oldField(oldObj);
205 MAddress oldAddress = oldField.GetFieldValue();
206
207 HeapAddress newAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
208 BaseObject* newObj = reinterpret_cast<BaseObject*>(newAddr);
209 constexpr size_t newSize = 200;
210 newObj->SetSizeForwarded(newSize);
211 EXPECT_EQ(newObj->GetSizeForwarded(), newSize);
212 RefField<false> newField(newObj);
213 MAddress neWAddress = newField.GetFieldValue();
214 EXPECT_NE(oldAddress, neWAddress);
215
216 idleBarrier->WriteRefField(oldObj, oldField, newObj);
217 EXPECT_EQ(oldField.GetFieldValue(), neWAddress);
218 }
219
HWTEST_F_L0(IdleBarrierTest,WriteRefField_TEST1)220 HWTEST_F_L0(IdleBarrierTest, WriteRefField_TEST1)
221 {
222 MockCollector collector;
223 auto idleBarrier = std::make_unique<IdleBarrier>(collector);
224 ASSERT_TRUE(idleBarrier != nullptr);
225
226 constexpr uint64_t TAG_BITS_SHIFT = 48;
227 constexpr uint64_t TAG_MARK = 0xFFFFULL << TAG_BITS_SHIFT;
228 constexpr uint64_t TAG_SPECIAL = 0x02ULL;
229 constexpr uint64_t TAG_BOOLEAN = 0x04ULL;
230 constexpr uint64_t TAG_HEAP_OBJECT_MASK = TAG_MARK | TAG_SPECIAL | TAG_BOOLEAN;
231
232 RefField<> field(MAddress(0));
233 BaseObject *obj = reinterpret_cast<BaseObject *>(TAG_HEAP_OBJECT_MASK);
234 idleBarrier->WriteRefField(obj, field, obj);
235 EXPECT_TRUE(obj != nullptr);
236 }
237
HWTEST_F_L0(IdleBarrierTest,WriteBarrier_TEST1)238 HWTEST_F_L0(IdleBarrierTest, WriteBarrier_TEST1)
239 {
240 MockCollector collector;
241 auto idleBarrier = std::make_unique<IdleBarrier>(collector);
242 ASSERT_TRUE(idleBarrier != nullptr);
243
244 constexpr uint64_t TAG_BITS_SHIFT = 48;
245 constexpr uint64_t TAG_MARK = 0xFFFFULL << TAG_BITS_SHIFT;
246 constexpr uint64_t TAG_SPECIAL = 0x02ULL;
247 constexpr uint64_t TAG_BOOLEAN = 0x04ULL;
248 constexpr uint64_t TAG_HEAP_OBJECT_MASK = TAG_MARK | TAG_SPECIAL | TAG_BOOLEAN;
249
250 RefField<> field(MAddress(0));
251 BaseObject *obj = reinterpret_cast<BaseObject *>(TAG_HEAP_OBJECT_MASK);
252 idleBarrier->WriteBarrier(obj, field, obj);
253 EXPECT_TRUE(obj != nullptr);
254 }
255
HWTEST_F_L0(IdleBarrierTest,WriteBarrier_TEST2)256 HWTEST_F_L0(IdleBarrierTest, WriteBarrier_TEST2)
257 {
258 MockCollector collector;
259 auto idleBarrier = std::make_unique<IdleBarrier>(collector);
260 ASSERT_TRUE(idleBarrier != nullptr);
261
262 HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
263 BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
264 RefField<> field(obj);
265 idleBarrier->WriteBarrier(obj, field, obj);
266 EXPECT_TRUE(obj != nullptr);
267 }
268
HWTEST_F_L0(IdleBarrierTest,WriteStruct_TEST0)269 HWTEST_F_L0(IdleBarrierTest, WriteStruct_TEST0)
270 {
271 MockCollector collector;
272 auto idleBarrier = std::make_unique<IdleBarrier>(collector);
273 ASSERT_TRUE(idleBarrier != nullptr);
274
275 HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
276 BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
277 HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
278 BaseObject* srcObj = reinterpret_cast<BaseObject*>(src);
279 srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING);
280 HeapAddress dst = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
281 BaseObject* dstObj = reinterpret_cast<BaseObject*>(dst);
282 dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED);
283 EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding());
284 idleBarrier->WriteStruct(obj, dst, sizeof(BaseObject), src, sizeof(BaseObject));
285 EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding());
286 }
287
HWTEST_F_L0(IdleBarrierTest,CopyStructArray_TEST0)288 HWTEST_F_L0(IdleBarrierTest, CopyStructArray_TEST0)
289 {
290 MockCollector collector;
291 auto idleBarrier = std::make_unique<IdleBarrier>(collector);
292 ASSERT_TRUE(idleBarrier != nullptr);
293
294 HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
295 BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
296 HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
297 BaseObject* srcObj = reinterpret_cast<BaseObject*>(src);
298 srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING);
299 HeapAddress dst = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
300 BaseObject* dstObj = reinterpret_cast<BaseObject*>(dst);
301 dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED);
302 EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding());
303 idleBarrier->CopyStructArray(obj, dst, sizeof(BaseObject), obj, src, sizeof(BaseObject));
304 EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding());
305 }
306 } // namespace common::test
307