• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2024 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 #ifndef PANDA_RUNTIME_TESTS_BITMAP_TEST_BASE_H
17 #define PANDA_RUNTIME_TESTS_BITMAP_TEST_BASE_H
18 
19 #include <cstdlib>
20 #include <memory>
21 #include <vector>
22 
23 #include "runtime/mem/gc/bitmap.h"
24 
25 namespace ark::mem {
26 
27 using BitmapWordType = ark::mem::Bitmap::BitmapWordType;
28 
FnRounddown(size_t val,size_t alignment)29 inline size_t FnRounddown(size_t val, size_t alignment)
30 {
31     size_t mask = ~((static_cast<size_t>(1) * alignment) - 1);
32     return val & mask;
33 }
34 
35 class BitmapTest : public testing::Test {
36 public:
37     static constexpr ObjectPointerType HEAP_STARTING_ADDRESS = static_cast<ObjectPointerType>(0x10000000);
38 
39     template <size_t K_ALIGNMENT, typename TestFn>
RunTest(TestFn && fn)40     static void RunTest(TestFn &&fn)
41     {
42         auto heapBegin = BitmapTest::HEAP_STARTING_ADDRESS;
43         const size_t heapCapacity = 16_MB;
44 #ifdef PANDA_NIGHTLY_TEST_ON
45         // NOLINTNEXTLINE(cert-msc51-cpp)
46         std::srand(time(nullptr));
47 #else
48         // NOLINTNEXTLINE(cert-msc51-cpp,readability-magic-numbers)
49         std::srand(0x1234);
50 #endif
51         constexpr int TEST_REPEAT = 1;
52         for (int i = 0; i < TEST_REPEAT; ++i) {
53             // NOLINTNEXTLINE(modernize-avoid-c-arrays)
54             auto bmPtr = std::make_unique<BitmapWordType[]>((heapCapacity >> Bitmap::LOG_BITSPERWORD) / K_ALIGNMENT);
55             MemBitmap<K_ALIGNMENT> bm(ToVoidPtr(heapBegin), heapCapacity, bmPtr.get());
56             constexpr int NUM_BITS_TO_MODIFY = 1000;
57             for (int j = 0; j < NUM_BITS_TO_MODIFY; ++j) {
58                 // NOLINTNEXTLINE(cert-msc50-cpp)
59                 size_t offset = FnRounddown(std::rand() % heapCapacity, K_ALIGNMENT);
60                 // NOLINTNEXTLINE(cert-msc50-cpp)
61                 bool set = std::rand() % 2 == 1;
62                 if (set) {
63                     bm.Set(ToVoidPtr(heapBegin + offset));
64                 } else {
65                     bm.Clear(ToVoidPtr(heapBegin + offset));
66                 }
67             }
68             constexpr int NUM_TEST_RANGES = 50;
69             for (int j = 0; j < NUM_TEST_RANGES; ++j) {
70                 // NOLINTNEXTLINE(cert-msc50-cpp)
71                 const size_t offset = FnRounddown(std::rand() % heapCapacity, K_ALIGNMENT);
72                 const size_t remain = heapCapacity - offset;
73                 // NOLINTNEXTLINE(cert-msc50-cpp)
74                 const size_t end = offset + FnRounddown(std::rand() % (remain + 1), K_ALIGNMENT);
75                 size_t manual = 0;
76                 for (ObjectPointerType k = offset; k < end; k += K_ALIGNMENT) {
77                     manual += bm.Test(ToVoidPtr(heapBegin + k)) ? 1U : 0U;
78                 }
79                 fn(&bm, heapBegin + offset, heapBegin + end, manual);
80             }
81         }
82     }
83 
84     template <size_t K_ALIGNMENT>
RunTestCount()85     static void RunTestCount()
86     {
87         auto countTestFn = [](MemBitmap<K_ALIGNMENT> *bitmap, ObjectPointerType begin, ObjectPointerType end,
88                               size_t manualCount) {
89             size_t count = 0;
90             auto countFn = [&count, begin, end]([[maybe_unused]] void *obj) {
91                 auto p = ToObjPtr(obj);
92                 if (p >= begin && p < end) {
93                     count++;
94                 }
95             };
96             bitmap->IterateOverMarkedChunkInRange(ToVoidPtr(begin), ToVoidPtr(end), countFn);
97             EXPECT_EQ(count, manualCount);
98         };
99         RunTest<K_ALIGNMENT>(countTestFn);
100     }
101 
102     template <size_t K_ALIGNMENT>
RunTestOrder()103     static void RunTestOrder()
104     {
105         auto orderTestFn = [](MemBitmap<K_ALIGNMENT> *bitmap, ObjectPointerType begin, ObjectPointerType end,
106                               size_t manualCount) {
107             void *lastPtr = nullptr;
108             auto orderCheck = [&lastPtr](void *obj) {
109                 EXPECT_LT(lastPtr, obj);
110                 lastPtr = obj;
111             };
112 
113             // Test complete walk.
114             bitmap->IterateOverChunks(orderCheck);
115             if (manualCount > 0) {
116                 EXPECT_NE(nullptr, lastPtr);
117             }
118 
119             // Test range.
120             lastPtr = nullptr;
121             bitmap->IterateOverMarkedChunkInRange(ToVoidPtr(begin), ToVoidPtr(end), orderCheck);
122             if (manualCount > 0) {
123                 EXPECT_NE(nullptr, lastPtr);
124             }
125         };
126         RunTest<K_ALIGNMENT>(orderTestFn);
127     }
128 };
129 
130 class BitmapVerify {
131 public:
132     using BitmapType = MemBitmap<DEFAULT_ALIGNMENT_IN_BYTES>;
BitmapVerify(BitmapType * bitmapArg,void * beginArg,void * endArg)133     BitmapVerify(BitmapType *bitmapArg, void *beginArg, void *endArg)
134         : bitmap_(bitmapArg), begin_(beginArg), end_(endArg)
135     {
136     }
137 
operator()138     void operator()(void *obj)
139     {
140         EXPECT_TRUE(obj >= begin_);
141         EXPECT_TRUE(obj <= end_);
142         EXPECT_EQ(bitmap_->Test(obj), ((BitmapType::ToPointerType(obj) & ADDRESS_MASK_TO_SET) != 0));
143     }
144 
145     static constexpr BitmapWordType ADDRESS_MASK_TO_SET = 0xF;
146 
147 private:
148     BitmapType *const bitmap_;
149     void *begin_;
150     void *end_;
151 };
152 
TEST_F(BitmapTest,AtomicClearSetTest)153 TEST_F(BitmapTest, AtomicClearSetTest)
154 {
155     void *object = ToVoidPtr(HEAP_STARTING_ADDRESS);
156     const size_t sz = 1_MB;
157     // NOLINTNEXTLINE(modernize-avoid-c-arrays)
158     auto bmPtr = std::make_unique<BitmapWordType[]>(sz >> MemBitmap<>::LOG_BITSPERWORD);
159     MemBitmap<> bm(ToVoidPtr(HEAP_STARTING_ADDRESS), sz, bmPtr.get());
160 
161     // Set bit
162     ASSERT_TRUE(bm.Test(object) == bm.AtomicTestAndSet(object));
163     ASSERT_TRUE(bm.Test(object));
164     ASSERT_TRUE(bm.AtomicTest(object));
165 
166     // Clear bit
167     ASSERT_TRUE(bm.Test(object) == bm.AtomicTestAndClear(object));
168     ASSERT_TRUE(!bm.Test(object));
169     ASSERT_TRUE(!bm.AtomicTest(object));
170 }
171 
172 }  // namespace ark::mem
173 
174 #endif  // PANDA_RUNTIME_TESTS_BITMAP_TEST_BASE_H
175