Path: blob/master/test/hotspot/gtest/utilities/test_bitMap_setops.cpp
41145 views
/*1* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223#include "precompiled.hpp"24#include "utilities/align.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"3132typedef BitMap::idx_t idx_t;33typedef BitMap::bm_word_t bm_word_t;3435inline idx_t word_align_down(idx_t bit) {36return align_down(bit, BitsPerWord);37}3839class BitMapMemory {40private:41idx_t _words;42bm_word_t* _memory;4344public:45BitMapMemory(idx_t bits) :46_words(BitMap::calc_size_in_words(bits)),47_memory(static_cast<bm_word_t*>(malloc(_words * sizeof(bm_word_t))))48{ }4950~BitMapMemory() {51free(_memory);52}5354BitMapView make_view(idx_t bits, bm_word_t value) {55vmassert(BitMap::calc_size_in_words(bits) <= _words, "invalid request");56STATIC_ASSERT(sizeof(bm_word_t) == sizeof(HeapWord));57Copy::fill_to_aligned_words((HeapWord*)_memory, _words, value);58return BitMapView(_memory, bits);59}6061bm_word_t* memory() { return _memory; }62};6364const idx_t aligned_size = 4 * BitsPerWord;65const idx_t unaligned_size = aligned_size - (BitsPerWord / 2);6667static bm_word_t make_even_bits() {68bm_word_t result = 1;69while (true) {70bm_word_t next = (result << 2) | 1;71if (next == result) {72return result;73}74result = next;75}76}7778const bm_word_t even_bits = make_even_bits();79const bm_word_t odd_bits = ~even_bits;80const bm_word_t one_bits = ~bm_word_t(0);81const bm_word_t zero_bits = 0;8283// Scoped set a clear bit and restore to clear.84class WithBitSet {85private:86BitMap& _bm;87idx_t _index;8889public:90WithBitSet(BitMap& bm, idx_t index) : _bm(bm), _index(index) {91// Failure may indicate test bug; can't use ASSERT_xxx in constructor.92EXPECT_FALSE(_bm.at(_index));93bm.set_bit(_index);94}9596~WithBitSet() {97_bm.clear_bit(_index);98}99};100101// Scoped clear a set bit and restore to set.102class WithBitClear {103private:104BitMap& _bm;105idx_t _index;106107public:108WithBitClear(BitMap& bm, idx_t index) : _bm(bm), _index(index) {109// Failure may indicate test bug; can't use ASSERT_xxx in constructor.110EXPECT_TRUE(_bm.at(_index));111bm.clear_bit(_index);112}113114~WithBitClear() {115_bm.set_bit(_index);116}117};118119//////////////////////////////////////////////////////////////////////////////120// bool is_same(const BitMap& bits);121122TEST(BitMap, is_same__aligned) {123BitMapMemory mx(aligned_size);124BitMapMemory my(aligned_size);125126BitMapView x = mx.make_view(aligned_size, even_bits);127BitMapView y = my.make_view(aligned_size, even_bits);128EXPECT_TRUE(x.is_same(y));129130WithBitClear wbc(x, aligned_size / 2);131EXPECT_FALSE(x.is_same(y));132}133134TEST(BitMap, is_same__unaligned) {135BitMapMemory mx(aligned_size);136BitMapMemory my(aligned_size);137138BitMapView x = mx.make_view(unaligned_size, even_bits);139BitMapView y = my.make_view(unaligned_size, even_bits);140141// Check that a difference beyond the end of x/y doesn't count.142{143BitMapView aligned = BitMapView(mx.memory(), aligned_size);144const idx_t index = aligned_size - 2;145STATIC_ASSERT(unaligned_size <= index);146147WithBitClear wbc(aligned, index);148EXPECT_TRUE(x.is_same(y));149}150151// Check that a difference in the final partial word does count.152{153idx_t index = unaligned_size - 2;154ASSERT_LE(word_align_down(unaligned_size), index);155156WithBitClear wbc(y, index);157EXPECT_FALSE(x.is_same(y));158}159}160161//////////////////////////////////////////////////////////////////////////////162// bool is_full();163// bool is_empty();164165TEST(BitMap, is_full_or_empty__aligned) {166BitMapMemory mx(aligned_size);167168{169BitMapView x = mx.make_view(aligned_size, even_bits);170EXPECT_FALSE(x.is_full());171EXPECT_FALSE(x.is_empty());172}173174{175BitMapView x = mx.make_view(aligned_size, zero_bits);176EXPECT_FALSE(x.is_full());177EXPECT_TRUE(x.is_empty());178}179180{181BitMapView x = mx.make_view(aligned_size, one_bits);182EXPECT_TRUE(x.is_full());183EXPECT_FALSE(x.is_empty());184}185}186187TEST(BitMap, is_full__unaligned) {188BitMapMemory mx(aligned_size);189190BitMapView x = mx.make_view(unaligned_size, one_bits);191EXPECT_TRUE(x.is_full());192193// Check that a missing bit beyond the end doesn't count.194{195idx_t index = aligned_size - 1;196BitMapView aligned = BitMapView(mx.memory(), aligned_size);197198WithBitClear wcb(aligned, index);199EXPECT_FALSE(aligned.is_full());200EXPECT_TRUE(x.is_full());201}202203// Check that a missing bit in the final partial word does count.204{205WithBitClear wcb(x, unaligned_size - 1);206EXPECT_FALSE(x.is_full());207}208}209210TEST(BitMap, is_empty__unaligned) {211BitMapMemory mx(aligned_size);212213BitMapView x = mx.make_view(unaligned_size, zero_bits);214EXPECT_TRUE(x.is_empty());215216// Check that a set bit beyond the end doesn't count.217{218idx_t index = aligned_size - 1;219BitMapView aligned = BitMapView(mx.memory(), aligned_size);220221WithBitSet wbs(aligned, index);222EXPECT_FALSE(aligned.is_empty());223EXPECT_TRUE(x.is_empty());224}225226// Check that a set bit in the final partial word does count.227{228WithBitSet wbs(x, unaligned_size - 1);229EXPECT_FALSE(x.is_empty());230}231}232233//////////////////////////////////////////////////////////////////////////////234// bool contains(const BitMap& bits);235236TEST(BitMap, contains__aligned) {237BitMapMemory mx(aligned_size);238BitMapMemory my(aligned_size);239240BitMapView x = mx.make_view(aligned_size, even_bits);241BitMapView y = my.make_view(aligned_size, even_bits);242EXPECT_TRUE(x.contains(y));243244WithBitClear wbc(x, aligned_size / 2);245EXPECT_FALSE(x.contains(y));246}247248TEST(BitMap, contains__unaligned) {249BitMapMemory mx(aligned_size);250BitMapMemory my(aligned_size);251252BitMapView x = mx.make_view(unaligned_size, even_bits);253BitMapView y = my.make_view(unaligned_size, even_bits);254255// Check that a missing bit beyond the end of x doesn't count.256{257BitMapView aligned = BitMapView(mx.memory(), aligned_size);258const idx_t index = aligned_size - 2;259STATIC_ASSERT(unaligned_size <= index);260261WithBitClear wbc(aligned, index);262EXPECT_TRUE(x.contains(y));263}264265// Check that a missing bit in the final partial word does count.266{267idx_t index = unaligned_size - 2;268ASSERT_LE(word_align_down(unaligned_size), index);269270WithBitClear wbc(x, index);271EXPECT_FALSE(x.contains(y));272}273}274275//////////////////////////////////////////////////////////////////////////////276// bool intersects(const BitMap& bits);277278TEST(BitMap, intersects__aligned) {279BitMapMemory mx(aligned_size);280BitMapMemory my(aligned_size);281282BitMapView x = mx.make_view(aligned_size, even_bits);283BitMapView y = my.make_view(aligned_size, zero_bits);284EXPECT_FALSE(x.intersects(y));285286ASSERT_TRUE(x.at(aligned_size / 2));287WithBitSet wbs(y, aligned_size / 2);288EXPECT_TRUE(x.intersects(y));289}290291TEST(BitMap, intersects__unaligned) {292BitMapMemory mx(aligned_size);293BitMapMemory my(aligned_size);294295BitMapView x = mx.make_view(unaligned_size, even_bits);296BitMapView y = my.make_view(unaligned_size, zero_bits);297EXPECT_FALSE(x.intersects(y));298299// Check that adding a bit beyond the end of y doesn't count.300{301BitMapView aligned_x = BitMapView(mx.memory(), aligned_size);302BitMapView aligned_y = BitMapView(my.memory(), aligned_size);303const idx_t index = aligned_size - 2;304STATIC_ASSERT(unaligned_size <= index);305ASSERT_TRUE(aligned_x.at(index));306307WithBitSet wbs(aligned_y, index);308EXPECT_FALSE(x.intersects(y));309}310311// Check that adding a bit in the final partial word does count.312{313idx_t index = unaligned_size - 2;314ASSERT_LE(word_align_down(unaligned_size), index);315ASSERT_TRUE(x.at(index));316317WithBitSet wbs(y, index);318EXPECT_TRUE(x.intersects(y));319}320}321322//////////////////////////////////////////////////////////////////////////////323// void set_from(const BitMap& bits);324// void set_union(const BitMap& bits);325// void set_difference(const BitMap& bits);326// void set_intersection(const BitMap& bits);327//328// bool set_union_with_result(const BitMap& bits);329// bool set_difference_with_result(const BitMap& bits);330// bool set_intersection_with_result(const BitMap& bits);331332static void check_tail_unmodified(BitMapMemory& mem,333idx_t bits,334bm_word_t fill_word) {335if (!is_aligned(bits, BitsPerWord)) {336idx_t last_word_bit_index = word_align_down(bits);337idx_t last_word_index = BitMap::calc_size_in_words(last_word_bit_index);338bm_word_t last_word = mem.memory()[last_word_index];339idx_t shift = bits - last_word_bit_index;340EXPECT_EQ(fill_word >> shift, last_word >> shift);341}342}343344static void check_mod_setop(void (BitMap::*f)(const BitMap&),345idx_t bits,346bm_word_t wx,347bm_word_t wy,348bm_word_t wexp) {349BitMapMemory mx(bits);350BitMapMemory my(bits);351BitMapMemory mexp(bits);352353BitMapView x = mx.make_view(bits, wx);354BitMapView y = my.make_view(bits, wy);355BitMapView exp = mexp.make_view(bits, wexp);356357(x.*f)(y);358359EXPECT_TRUE(exp.is_same(x));360check_tail_unmodified(mx, bits, wx);361}362363static void check_mod_setop_with_result(bool (BitMap::*f)(const BitMap&),364idx_t bits,365bm_word_t wx,366bm_word_t wy,367bm_word_t wexp) {368BitMapMemory mx(bits);369BitMapMemory my(bits);370BitMapMemory mexp(bits);371372BitMapView x = mx.make_view(bits, wx);373BitMapView y = my.make_view(bits, wy);374BitMapView exp = mexp.make_view(bits, wexp);375376bool value = (x.*f)(y);377EXPECT_EQ(value, wx != wexp);378379EXPECT_TRUE(exp.is_same(x));380check_tail_unmodified(mx, bits, wx);381}382383#define CHECK_MOD_SETOP_AUX(checker, name, x, y, exp) \384TEST(BitMap, name ## __ ## x ## _ ## y) { \385checker(&BitMap::name, aligned_size, \386x ## _bits, y ## _bits, exp ## _bits); \387checker(&BitMap::name, unaligned_size, \388x ## _bits, y ## _bits, exp ## _bits); \389}390391#define CHECK_MOD_SETOP(name, x, y, exp) \392CHECK_MOD_SETOP_AUX(check_mod_setop, name, x, y, exp)393394#define CHECK_MOD_SETOP_WITH_RESULT(name, x, y, exp) \395CHECK_MOD_SETOP_AUX(check_mod_setop_with_result, name, x, y, exp)396397#define CHECK_MOD_SETOPS(name, x, y, exp) \398CHECK_MOD_SETOP(name, x, y, exp) \399CHECK_MOD_SETOP_WITH_RESULT(name ## _with_result, x, y, exp)400401CHECK_MOD_SETOP(set_from, even, even, even)402CHECK_MOD_SETOP(set_from, even, odd, odd)403CHECK_MOD_SETOP(set_from, even, one, one)404CHECK_MOD_SETOP(set_from, even, zero, zero)405406CHECK_MOD_SETOPS(set_union, even, even, even)407CHECK_MOD_SETOPS(set_union, even, odd, one)408CHECK_MOD_SETOPS(set_union, even, one, one)409CHECK_MOD_SETOPS(set_union, even, zero, even)410411CHECK_MOD_SETOPS(set_difference, even, even, zero)412CHECK_MOD_SETOPS(set_difference, even, odd, even)413CHECK_MOD_SETOPS(set_difference, even, one, zero)414CHECK_MOD_SETOPS(set_difference, even, zero, even)415416CHECK_MOD_SETOPS(set_intersection, even, even, even)417CHECK_MOD_SETOPS(set_intersection, even, odd, zero)418CHECK_MOD_SETOPS(set_intersection, even, one, even)419CHECK_MOD_SETOPS(set_intersection, even, zero, zero)420421422423