1 /* 2 * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2020 SAP SE. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26 #include "precompiled.hpp" 27 #include "memory/metaspace/binList.hpp" 28 #include "memory/metaspace/counters.hpp" 29 #include "memory/metaspace/metablock.hpp" 30 //#define LOG_PLEASE 31 #include "metaspaceGtestCommon.hpp" 32 33 using metaspace::BinList32; 34 using metaspace::BinListImpl; 35 using metaspace::MemRangeCounter; 36 using metaspace::MetaBlock; 37 38 #define CHECK_BL_CONTENT(bl, expected_num, expected_size) { \ 39 EXPECT_EQ(bl.count(), (unsigned)expected_num); \ 40 EXPECT_EQ(bl.total_size(), (size_t)expected_size); \ 41 if (expected_num == 0) { \ 42 EXPECT_TRUE(bl.is_empty()); \ 43 } else { \ 44 EXPECT_FALSE(bl.is_empty()); \ 45 } \ 46 } 47 48 template <int num_lists> 49 struct TestedBinList : public BinListImpl<num_lists> { 50 typedef BinListImpl<num_lists> ListType; 51 void add_block(MetaWord* p, size_t word_size) { 52 ListType::add_block(MetaBlock(p, word_size)); 53 } 54 MetaWord* remove_block(size_t requested_size, size_t* real_size) { 55 MetaBlock result = ListType::remove_block(requested_size); 56 (*real_size) = result.word_size(); 57 return result.base(); 58 } 59 }; 60 61 template <class BINLISTTYPE> 62 struct BinListBasicTest { 63 64 static const size_t maxws; 65 66 static void basic_test() { 67 68 BINLISTTYPE bl; 69 70 CHECK_BL_CONTENT(bl, 0, 0); 71 72 MetaWord arr[1000]; 73 74 size_t innocous_size = MAX2((size_t)1, maxws / 2); 75 76 // Try to get a block from an empty list. 77 size_t real_size = 4711; 78 MetaWord* p = bl.remove_block(innocous_size, &real_size); 79 EXPECT_EQ(p, (MetaWord*)nullptr); 80 EXPECT_EQ((size_t)0, real_size); 81 82 // Add a block... 83 bl.add_block(arr, innocous_size); 84 CHECK_BL_CONTENT(bl, 1, innocous_size); 85 DEBUG_ONLY(bl.verify();) 86 87 // And retrieve it. 88 real_size = 4711; 89 p = bl.remove_block(innocous_size, &real_size); 90 EXPECT_EQ(p, arr); 91 EXPECT_EQ((size_t)innocous_size, real_size); 92 CHECK_BL_CONTENT(bl, 0, 0); 93 DEBUG_ONLY(bl.verify();) 94 95 } 96 97 static void basic_test_2() { 98 99 BINLISTTYPE bl; 100 101 CHECK_BL_CONTENT(bl, 0, 0); 102 103 MetaWord arr[1000]; 104 105 for (size_t s1 = 1; s1 <= maxws; s1++) { 106 for (size_t s2 = 1; s2 <= maxws; s2++) { 107 108 bl.add_block(arr, s1); 109 CHECK_BL_CONTENT(bl, 1, s1); 110 DEBUG_ONLY(bl.verify();) 111 112 size_t real_size = 4711; 113 MetaWord* p = bl.remove_block(s2, &real_size); 114 if (s1 >= s2) { 115 EXPECT_EQ(p, arr); 116 EXPECT_EQ((size_t)s1, real_size); 117 CHECK_BL_CONTENT(bl, 0, 0); 118 DEBUG_ONLY(bl.verify();) 119 } else { 120 EXPECT_EQ(p, (MetaWord*)nullptr); 121 EXPECT_EQ((size_t)0, real_size); 122 CHECK_BL_CONTENT(bl, 1, s1); 123 DEBUG_ONLY(bl.verify();) 124 // drain bl 125 p = bl.remove_block(1, &real_size); 126 EXPECT_EQ(p, arr); 127 EXPECT_EQ((size_t)s1, real_size); 128 CHECK_BL_CONTENT(bl, 0, 0); 129 } 130 } 131 } 132 } 133 134 static void random_test() { 135 136 BINLISTTYPE bl[2]; 137 MemRangeCounter cnt[2]; 138 139 #define CHECK_COUNTERS \ 140 ASSERT_EQ(cnt[0].count(), bl[0].count()); \ 141 ASSERT_EQ(cnt[1].count(), bl[1].count()); \ 142 ASSERT_EQ(cnt[0].total_size(), bl[0].total_size()); \ 143 ASSERT_EQ(cnt[1].total_size(), bl[1].total_size()); 144 145 FeederBuffer fb(1024); 146 RandSizeGenerator rgen(1, maxws + 1); 147 148 // feed all 149 int which = 0; 150 for (;;) { 151 size_t s = rgen.get(); 152 MetaWord* p = fb.get(s); 153 if (p != nullptr) { 154 bl[which].add_block(p, s); 155 cnt[which].add(s); 156 which = which == 0 ? 1 : 0; 157 } else { 158 break; 159 } 160 } 161 162 CHECK_COUNTERS; 163 DEBUG_ONLY(bl[0].verify();) 164 DEBUG_ONLY(bl[1].verify();) 165 166 // play pingpong 167 for (int iter = 0; iter < 1000; iter++) { 168 size_t s = rgen.get(); 169 int taker = iter % 2; 170 int giver = taker == 0 ? 1 : 0; 171 172 size_t real_size = 4711; 173 MetaWord* p = bl[giver].remove_block(s, &real_size); 174 if (p != nullptr) { 175 176 ASSERT_TRUE(fb.is_valid_range(p, real_size)); 177 ASSERT_GE(real_size, s); 178 cnt[giver].sub(real_size); 179 180 bl[taker].add_block(p, real_size); 181 cnt[taker].add(real_size); 182 183 } else { 184 ASSERT_EQ(real_size, (size_t)nullptr); 185 } 186 187 CHECK_COUNTERS; 188 189 } 190 191 CHECK_COUNTERS; 192 DEBUG_ONLY(bl[0].verify();) 193 DEBUG_ONLY(bl[1].verify();) 194 195 // drain both lists. 196 for (int which = 0; which < 2; which++) { 197 size_t last_size = 0; 198 while (bl[which].is_empty() == false) { 199 200 size_t real_size = 4711; 201 MetaWord* p = bl[which].remove_block(1, &real_size); 202 203 ASSERT_NE(p, (MetaWord*) nullptr); 204 ASSERT_GE(real_size, (size_t)1); 205 ASSERT_TRUE(fb.is_valid_range(p, real_size)); 206 207 // This must hold true since we always return the smallest fit. 208 ASSERT_GE(real_size, last_size); 209 if (real_size > last_size) { 210 last_size = real_size; 211 } 212 213 cnt[which].sub(real_size); 214 215 CHECK_COUNTERS; 216 } 217 } 218 219 } 220 }; 221 222 template <typename BINLISTTYPE> const size_t BinListBasicTest<BINLISTTYPE>::maxws = BINLISTTYPE::MaxWordSize; 223 224 TEST_VM(metaspace, BinList_basic_1) { BinListBasicTest< TestedBinList<1> >::basic_test(); } 225 TEST_VM(metaspace, BinList_basic_8) { BinListBasicTest< TestedBinList<8> >::basic_test(); } 226 TEST_VM(metaspace, BinList_basic_32) { BinListBasicTest< TestedBinList<32> >::basic_test(); } 227 228 TEST_VM(metaspace, BinList_basic_2_1) { BinListBasicTest< TestedBinList<1> >::basic_test_2(); } 229 TEST_VM(metaspace, BinList_basic_2_8) { BinListBasicTest< TestedBinList<8> >::basic_test_2(); } 230 TEST_VM(metaspace, BinList_basic_2_32) { BinListBasicTest< TestedBinList<32> >::basic_test_2(); } 231 232 TEST_VM(metaspace, BinList_basic_rand_1) { BinListBasicTest< TestedBinList<1> >::random_test(); } 233 TEST_VM(metaspace, BinList_basic_rand_8) { BinListBasicTest< TestedBinList<8> >::random_test(); } 234 TEST_VM(metaspace, BinList_basic_rand_32) { BinListBasicTest< TestedBinList<32> >::random_test(); }