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