1 /* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 #include "precompiled.hpp" 25 #include "utilities/bitMap.inline.hpp" 26 #include "utilities/copy.hpp" 27 #include "utilities/debug.hpp" 28 #include "utilities/globalDefinitions.hpp" 29 #include <stdlib.h> 30 #include "unittest.hpp" 31 32 typedef BitMap::idx_t idx_t; 33 typedef BitMap::bm_word_t bm_word_t; 34 35 class BitMapMemory { 36 private: 37 idx_t _words; 38 bm_word_t* _memory; 39 40 public: 41 BitMapMemory(idx_t bits) : 42 _words(BitMap::calc_size_in_words(bits)), 43 _memory(static_cast<bm_word_t*>(malloc(_words * sizeof(bm_word_t)))) 44 { } 45 46 ~BitMapMemory() { 47 free(_memory); 48 } 49 50 BitMapView make_view(idx_t bits, bm_word_t value) { 51 vmassert(BitMap::calc_size_in_words(bits) <= _words, "invalid request"); 52 STATIC_ASSERT(sizeof(bm_word_t) == sizeof(HeapWord)); 53 Copy::fill_to_aligned_words((HeapWord*)_memory, _words, value); 54 return BitMapView(_memory, bits); 55 } 56 57 bm_word_t* memory() { return _memory; } 58 }; 59 60 const idx_t aligned_size = 4 * BitsPerWord; 61 const idx_t unaligned_size = aligned_size - (BitsPerWord / 2); 62 63 static bm_word_t make_even_bits() { 64 bm_word_t result = 1; 65 while (true) { 66 bm_word_t next = (result << 2) | 1; 67 if (next == result) { 68 return result; 69 } 70 result = next; 71 } 72 } 73 74 const bm_word_t even_bits = make_even_bits(); 75 const bm_word_t odd_bits = ~even_bits; 76 const bm_word_t one_bits = ~bm_word_t(0); 77 const bm_word_t zero_bits = 0; 78 79 // Scoped set a clear bit and restore to clear. 80 class WithBitSet { 81 private: 82 BitMap& _bm; 83 idx_t _index; 84 85 public: 86 WithBitSet(BitMap& bm, idx_t index) : _bm(bm), _index(index) { 87 // Failure may indicate test bug; can't use ASSERT_xxx in constructor. 88 EXPECT_FALSE(_bm.at(_index)); 89 bm.set_bit(_index); 90 } 91 92 ~WithBitSet() { 93 _bm.clear_bit(_index); 94 } 95 }; 96 97 // Scoped clear a set bit and restore to set. 98 class WithBitClear { 99 private: 100 BitMap& _bm; 101 idx_t _index; 102 103 public: 104 WithBitClear(BitMap& bm, idx_t index) : _bm(bm), _index(index) { 105 // Failure may indicate test bug; can't use ASSERT_xxx in constructor. 106 EXPECT_TRUE(_bm.at(_index)); 107 bm.clear_bit(_index); 108 } 109 110 ~WithBitClear() { 111 _bm.set_bit(_index); 112 } 113 }; 114 115 ////////////////////////////////////////////////////////////////////////////// 116 // bool is_same(const BitMap& bits); 117 118 TEST(BitMap, is_same__aligned) { 119 BitMapMemory mx(aligned_size); 120 BitMapMemory my(aligned_size); 121 122 BitMapView x = mx.make_view(aligned_size, even_bits); 123 BitMapView y = my.make_view(aligned_size, even_bits); 124 EXPECT_TRUE(x.is_same(y)); 125 126 WithBitClear wbc(x, aligned_size / 2); 127 EXPECT_FALSE(x.is_same(y)); 128 } 129 130 TEST(BitMap, is_same__unaligned) { 131 BitMapMemory mx(aligned_size); 132 BitMapMemory my(aligned_size); 133 134 BitMapView x = mx.make_view(unaligned_size, even_bits); 135 BitMapView y = my.make_view(unaligned_size, even_bits); 136 137 // Check that a difference beyond the end of x/y doesn't count. 138 { 139 BitMapView aligned = BitMapView(mx.memory(), aligned_size); 140 const idx_t index = aligned_size - 2; 141 STATIC_ASSERT(unaligned_size <= index); 142 143 WithBitClear wbc(aligned, index); 144 EXPECT_TRUE(x.is_same(y)); 145 } 146 147 // Check that a difference in the final partial word does count. 148 { 149 idx_t index = unaligned_size - 2; 150 ASSERT_LE(BitMap::word_align_down(unaligned_size), index); 151 152 WithBitClear wbc(y, index); 153 EXPECT_FALSE(x.is_same(y)); 154 } 155 } 156 157 ////////////////////////////////////////////////////////////////////////////// 158 // bool is_full(); 159 // bool is_empty(); 160 161 TEST(BitMap, is_full_or_empty__aligned) { 162 BitMapMemory mx(aligned_size); 163 164 { 165 BitMapView x = mx.make_view(aligned_size, even_bits); 166 EXPECT_FALSE(x.is_full()); 167 EXPECT_FALSE(x.is_empty()); 168 } 169 170 { 171 BitMapView x = mx.make_view(aligned_size, zero_bits); 172 EXPECT_FALSE(x.is_full()); 173 EXPECT_TRUE(x.is_empty()); 174 } 175 176 { 177 BitMapView x = mx.make_view(aligned_size, one_bits); 178 EXPECT_TRUE(x.is_full()); 179 EXPECT_FALSE(x.is_empty()); 180 } 181 } 182 183 TEST(BitMap, is_full__unaligned) { 184 BitMapMemory mx(aligned_size); 185 186 BitMapView x = mx.make_view(unaligned_size, one_bits); 187 EXPECT_TRUE(x.is_full()); 188 189 // Check that a missing bit beyond the end doesn't count. 190 { 191 idx_t index = aligned_size - 1; 192 BitMapView aligned = BitMapView(mx.memory(), aligned_size); 193 194 WithBitClear wcb(aligned, index); 195 EXPECT_FALSE(aligned.is_full()); 196 EXPECT_TRUE(x.is_full()); 197 } 198 199 // Check that a missing bit in the final partial word does count. 200 { 201 WithBitClear wcb(x, unaligned_size - 1); 202 EXPECT_FALSE(x.is_full()); 203 } 204 } 205 206 TEST(BitMap, is_empty__unaligned) { 207 BitMapMemory mx(aligned_size); 208 209 BitMapView x = mx.make_view(unaligned_size, zero_bits); 210 EXPECT_TRUE(x.is_empty()); 211 212 // Check that a set bit beyond the end doesn't count. 213 { 214 idx_t index = aligned_size - 1; 215 BitMapView aligned = BitMapView(mx.memory(), aligned_size); 216 217 WithBitSet wbs(aligned, index); 218 EXPECT_FALSE(aligned.is_empty()); 219 EXPECT_TRUE(x.is_empty()); 220 } 221 222 // Check that a set bit in the final partial word does count. 223 { 224 WithBitSet wbs(x, unaligned_size - 1); 225 EXPECT_FALSE(x.is_empty()); 226 } 227 } 228 229 ////////////////////////////////////////////////////////////////////////////// 230 // bool contains(const BitMap& bits); 231 232 TEST(BitMap, contains__aligned) { 233 BitMapMemory mx(aligned_size); 234 BitMapMemory my(aligned_size); 235 236 BitMapView x = mx.make_view(aligned_size, even_bits); 237 BitMapView y = my.make_view(aligned_size, even_bits); 238 EXPECT_TRUE(x.contains(y)); 239 240 WithBitClear wbc(x, aligned_size / 2); 241 EXPECT_FALSE(x.contains(y)); 242 } 243 244 TEST(BitMap, contains__unaligned) { 245 BitMapMemory mx(aligned_size); 246 BitMapMemory my(aligned_size); 247 248 BitMapView x = mx.make_view(unaligned_size, even_bits); 249 BitMapView y = my.make_view(unaligned_size, even_bits); 250 251 // Check that a missing bit beyond the end of x doesn't count. 252 { 253 BitMapView aligned = BitMapView(mx.memory(), aligned_size); 254 const idx_t index = aligned_size - 2; 255 STATIC_ASSERT(unaligned_size <= index); 256 257 WithBitClear wbc(aligned, index); 258 EXPECT_TRUE(x.contains(y)); 259 } 260 261 // Check that a missing bit in the final partial word does count. 262 { 263 idx_t index = unaligned_size - 2; 264 ASSERT_LE(BitMap::word_align_down(unaligned_size), index); 265 266 WithBitClear wbc(x, index); 267 EXPECT_FALSE(x.contains(y)); 268 } 269 } 270 271 ////////////////////////////////////////////////////////////////////////////// 272 // bool intersects(const BitMap& bits); 273 274 TEST(BitMap, intersects__aligned) { 275 BitMapMemory mx(aligned_size); 276 BitMapMemory my(aligned_size); 277 278 BitMapView x = mx.make_view(aligned_size, even_bits); 279 BitMapView y = my.make_view(aligned_size, zero_bits); 280 EXPECT_FALSE(x.intersects(y)); 281 282 ASSERT_TRUE(x.at(aligned_size / 2)); 283 WithBitSet wbs(y, aligned_size / 2); 284 EXPECT_TRUE(x.intersects(y)); 285 } 286 287 TEST(BitMap, intersects__unaligned) { 288 BitMapMemory mx(aligned_size); 289 BitMapMemory my(aligned_size); 290 291 BitMapView x = mx.make_view(unaligned_size, even_bits); 292 BitMapView y = my.make_view(unaligned_size, zero_bits); 293 EXPECT_FALSE(x.intersects(y)); 294 295 // Check that adding a bit beyond the end of y doesn't count. 296 { 297 BitMapView aligned_x = BitMapView(mx.memory(), aligned_size); 298 BitMapView aligned_y = BitMapView(my.memory(), aligned_size); 299 const idx_t index = aligned_size - 2; 300 STATIC_ASSERT(unaligned_size <= index); 301 ASSERT_TRUE(aligned_x.at(index)); 302 303 WithBitSet wbs(aligned_y, index); 304 EXPECT_FALSE(x.intersects(y)); 305 } 306 307 // Check that adding a bit in the final partial word does count. 308 { 309 idx_t index = unaligned_size - 2; 310 ASSERT_LE(BitMap::word_align_down(unaligned_size), index); 311 ASSERT_TRUE(x.at(index)); 312 313 WithBitSet wbs(y, index); 314 EXPECT_TRUE(x.intersects(y)); 315 } 316 } 317 318 ////////////////////////////////////////////////////////////////////////////// 319 // void set_from(const BitMap& bits); 320 // void set_union(const BitMap& bits); 321 // void set_difference(const BitMap& bits); 322 // void set_intersection(const BitMap& bits); 323 // 324 // bool set_union_with_result(const BitMap& bits); 325 // bool set_difference_with_result(const BitMap& bits); 326 // bool set_intersection_with_result(const BitMap& bits); 327 328 static void check_tail_unmodified(BitMapMemory& mem, 329 idx_t bits, 330 bm_word_t fill_word) { 331 if (!BitMap::is_word_aligned(bits)) { 332 idx_t last_word_bit_index = BitMap::word_align_down(bits); 333 idx_t last_word_index = BitMap::calc_size_in_words(last_word_bit_index); 334 bm_word_t last_word = mem.memory()[last_word_index]; 335 idx_t shift = bits - last_word_bit_index; 336 EXPECT_EQ(fill_word >> shift, last_word >> shift); 337 } 338 } 339 340 static void check_mod_setop(void (BitMap::*f)(const BitMap&), 341 idx_t bits, 342 bm_word_t wx, 343 bm_word_t wy, 344 bm_word_t wexp) { 345 BitMapMemory mx(bits); 346 BitMapMemory my(bits); 347 BitMapMemory mexp(bits); 348 349 BitMapView x = mx.make_view(bits, wx); 350 BitMapView y = my.make_view(bits, wy); 351 BitMapView exp = mexp.make_view(bits, wexp); 352 353 (x.*f)(y); 354 355 EXPECT_TRUE(exp.is_same(x)); 356 check_tail_unmodified(mx, bits, wx); 357 } 358 359 static void check_mod_setop_with_result(bool (BitMap::*f)(const BitMap&), 360 idx_t bits, 361 bm_word_t wx, 362 bm_word_t wy, 363 bm_word_t wexp) { 364 BitMapMemory mx(bits); 365 BitMapMemory my(bits); 366 BitMapMemory mexp(bits); 367 368 BitMapView x = mx.make_view(bits, wx); 369 BitMapView y = my.make_view(bits, wy); 370 BitMapView exp = mexp.make_view(bits, wexp); 371 372 bool value = (x.*f)(y); 373 EXPECT_EQ(value, wx != wexp); 374 375 EXPECT_TRUE(exp.is_same(x)); 376 check_tail_unmodified(mx, bits, wx); 377 } 378 379 #define CHECK_MOD_SETOP_AUX(checker, name, x, y, exp) \ 380 TEST(BitMap, name ## __ ## x ## _ ## y) { \ 381 checker(&BitMap::name, aligned_size, \ 382 x ## _bits, y ## _bits, exp ## _bits); \ 383 checker(&BitMap::name, unaligned_size, \ 384 x ## _bits, y ## _bits, exp ## _bits); \ 385 } 386 387 #define CHECK_MOD_SETOP(name, x, y, exp) \ 388 CHECK_MOD_SETOP_AUX(check_mod_setop, name, x, y, exp) 389 390 #define CHECK_MOD_SETOP_WITH_RESULT(name, x, y, exp) \ 391 CHECK_MOD_SETOP_AUX(check_mod_setop_with_result, name, x, y, exp) 392 393 #define CHECK_MOD_SETOPS(name, x, y, exp) \ 394 CHECK_MOD_SETOP(name, x, y, exp) \ 395 CHECK_MOD_SETOP_WITH_RESULT(name ## _with_result, x, y, exp) 396 397 CHECK_MOD_SETOP(set_from, even, even, even) 398 CHECK_MOD_SETOP(set_from, even, odd, odd) 399 CHECK_MOD_SETOP(set_from, even, one, one) 400 CHECK_MOD_SETOP(set_from, even, zero, zero) 401 402 CHECK_MOD_SETOPS(set_union, even, even, even) 403 CHECK_MOD_SETOPS(set_union, even, odd, one) 404 CHECK_MOD_SETOPS(set_union, even, one, one) 405 CHECK_MOD_SETOPS(set_union, even, zero, even) 406 407 CHECK_MOD_SETOPS(set_difference, even, even, zero) 408 CHECK_MOD_SETOPS(set_difference, even, odd, even) 409 CHECK_MOD_SETOPS(set_difference, even, one, zero) 410 CHECK_MOD_SETOPS(set_difference, even, zero, even) 411 412 CHECK_MOD_SETOPS(set_intersection, even, even, even) 413 CHECK_MOD_SETOPS(set_intersection, even, odd, zero) 414 CHECK_MOD_SETOPS(set_intersection, even, one, even) 415 CHECK_MOD_SETOPS(set_intersection, even, zero, zero) 416