src/share/vm/utilities/bitMap.cpp

Wed, 24 Feb 2010 07:00:33 -0800

author
jmasa
date
Wed, 24 Feb 2010 07:00:33 -0800
changeset 1719
5f1f51edaff6
parent 1279
bd02caa94611
child 1907
c18cbe5936b8
permissions
-rw-r--r--

6928081: G1: rename parameters common with CMS
Summary: Rename marking stack sizing flags to be common between G1 and CMS
Reviewed-by: ysr, tonyp

     1 /*
     2  * Copyright 1997-2009 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
    21  * have any questions.
    22  *
    23  */
    25 # include "incls/_precompiled.incl"
    26 # include "incls/_bitMap.cpp.incl"
    29 BitMap::BitMap(bm_word_t* map, idx_t size_in_bits) :
    30   _map(map), _size(size_in_bits)
    31 {
    32   assert(sizeof(bm_word_t) == BytesPerWord, "Implementation assumption.");
    33   assert(size_in_bits >= 0, "just checking");
    34 }
    37 BitMap::BitMap(idx_t size_in_bits, bool in_resource_area) :
    38   _map(NULL), _size(0)
    39 {
    40   assert(sizeof(bm_word_t) == BytesPerWord, "Implementation assumption.");
    41   resize(size_in_bits, in_resource_area);
    42 }
    44 void BitMap::resize(idx_t size_in_bits, bool in_resource_area) {
    45   assert(size_in_bits >= 0, "just checking");
    46   idx_t old_size_in_words = size_in_words();
    47   bm_word_t* old_map = map();
    49   _size = size_in_bits;
    50   idx_t new_size_in_words = size_in_words();
    51   if (in_resource_area) {
    52     _map = NEW_RESOURCE_ARRAY(bm_word_t, new_size_in_words);
    53   } else {
    54     if (old_map != NULL) FREE_C_HEAP_ARRAY(bm_word_t, _map);
    55     _map = NEW_C_HEAP_ARRAY(bm_word_t, new_size_in_words);
    56   }
    57   Copy::disjoint_words((HeapWord*)old_map, (HeapWord*) _map,
    58                        MIN2(old_size_in_words, new_size_in_words));
    59   if (new_size_in_words > old_size_in_words) {
    60     clear_range_of_words(old_size_in_words, size_in_words());
    61   }
    62 }
    64 void BitMap::set_range_within_word(idx_t beg, idx_t end) {
    65   // With a valid range (beg <= end), this test ensures that end != 0, as
    66   // required by inverted_bit_mask_for_range.  Also avoids an unnecessary write.
    67   if (beg != end) {
    68     bm_word_t mask = inverted_bit_mask_for_range(beg, end);
    69     *word_addr(beg) |= ~mask;
    70   }
    71 }
    73 void BitMap::clear_range_within_word(idx_t beg, idx_t end) {
    74   // With a valid range (beg <= end), this test ensures that end != 0, as
    75   // required by inverted_bit_mask_for_range.  Also avoids an unnecessary write.
    76   if (beg != end) {
    77     bm_word_t mask = inverted_bit_mask_for_range(beg, end);
    78     *word_addr(beg) &= mask;
    79   }
    80 }
    82 void BitMap::par_put_range_within_word(idx_t beg, idx_t end, bool value) {
    83   assert(value == 0 || value == 1, "0 for clear, 1 for set");
    84   // With a valid range (beg <= end), this test ensures that end != 0, as
    85   // required by inverted_bit_mask_for_range.  Also avoids an unnecessary write.
    86   if (beg != end) {
    87     intptr_t* pw  = (intptr_t*)word_addr(beg);
    88     intptr_t  w   = *pw;
    89     intptr_t  mr  = (intptr_t)inverted_bit_mask_for_range(beg, end);
    90     intptr_t  nw  = value ? (w | ~mr) : (w & mr);
    91     while (true) {
    92       intptr_t res = Atomic::cmpxchg_ptr(nw, pw, w);
    93       if (res == w) break;
    94       w  = *pw;
    95       nw = value ? (w | ~mr) : (w & mr);
    96     }
    97   }
    98 }
   100 void BitMap::set_range(idx_t beg, idx_t end) {
   101   verify_range(beg, end);
   103   idx_t beg_full_word = word_index_round_up(beg);
   104   idx_t end_full_word = word_index(end);
   106   if (beg_full_word < end_full_word) {
   107     // The range includes at least one full word.
   108     set_range_within_word(beg, bit_index(beg_full_word));
   109     set_range_of_words(beg_full_word, end_full_word);
   110     set_range_within_word(bit_index(end_full_word), end);
   111   } else {
   112     // The range spans at most 2 partial words.
   113     idx_t boundary = MIN2(bit_index(beg_full_word), end);
   114     set_range_within_word(beg, boundary);
   115     set_range_within_word(boundary, end);
   116   }
   117 }
   119 void BitMap::clear_range(idx_t beg, idx_t end) {
   120   verify_range(beg, end);
   122   idx_t beg_full_word = word_index_round_up(beg);
   123   idx_t end_full_word = word_index(end);
   125   if (beg_full_word < end_full_word) {
   126     // The range includes at least one full word.
   127     clear_range_within_word(beg, bit_index(beg_full_word));
   128     clear_range_of_words(beg_full_word, end_full_word);
   129     clear_range_within_word(bit_index(end_full_word), end);
   130   } else {
   131     // The range spans at most 2 partial words.
   132     idx_t boundary = MIN2(bit_index(beg_full_word), end);
   133     clear_range_within_word(beg, boundary);
   134     clear_range_within_word(boundary, end);
   135   }
   136 }
   138 void BitMap::set_large_range(idx_t beg, idx_t end) {
   139   verify_range(beg, end);
   141   idx_t beg_full_word = word_index_round_up(beg);
   142   idx_t end_full_word = word_index(end);
   144   assert(end_full_word - beg_full_word >= 32,
   145          "the range must include at least 32 bytes");
   147   // The range includes at least one full word.
   148   set_range_within_word(beg, bit_index(beg_full_word));
   149   set_large_range_of_words(beg_full_word, end_full_word);
   150   set_range_within_word(bit_index(end_full_word), end);
   151 }
   153 void BitMap::clear_large_range(idx_t beg, idx_t end) {
   154   verify_range(beg, end);
   156   idx_t beg_full_word = word_index_round_up(beg);
   157   idx_t end_full_word = word_index(end);
   159   assert(end_full_word - beg_full_word >= 32,
   160          "the range must include at least 32 bytes");
   162   // The range includes at least one full word.
   163   clear_range_within_word(beg, bit_index(beg_full_word));
   164   clear_large_range_of_words(beg_full_word, end_full_word);
   165   clear_range_within_word(bit_index(end_full_word), end);
   166 }
   168 void BitMap::mostly_disjoint_range_union(BitMap* from_bitmap,
   169                                          idx_t   from_start_index,
   170                                          idx_t   to_start_index,
   171                                          size_t  word_num) {
   172   // Ensure that the parameters are correct.
   173   // These shouldn't be that expensive to check, hence I left them as
   174   // guarantees.
   175   guarantee(from_bitmap->bit_in_word(from_start_index) == 0,
   176             "it should be aligned on a word boundary");
   177   guarantee(bit_in_word(to_start_index) == 0,
   178             "it should be aligned on a word boundary");
   179   guarantee(word_num >= 2, "word_num should be at least 2");
   181   intptr_t* from = (intptr_t*) from_bitmap->word_addr(from_start_index);
   182   intptr_t* to   = (intptr_t*) word_addr(to_start_index);
   184   if (*from != 0) {
   185     // if it's 0, then there's no point in doing the CAS
   186     while (true) {
   187       intptr_t old_value = *to;
   188       intptr_t new_value = old_value | *from;
   189       intptr_t res       = Atomic::cmpxchg_ptr(new_value, to, old_value);
   190       if (res == old_value) break;
   191     }
   192   }
   193   ++from;
   194   ++to;
   196   for (size_t i = 0; i < word_num - 2; ++i) {
   197     if (*from != 0) {
   198       // if it's 0, then there's no point in doing the CAS
   199       assert(*to == 0, "nobody else should be writing here");
   200       intptr_t new_value = *from;
   201       *to = new_value;
   202     }
   204     ++from;
   205     ++to;
   206   }
   208   if (*from != 0) {
   209     // if it's 0, then there's no point in doing the CAS
   210     while (true) {
   211       intptr_t old_value = *to;
   212       intptr_t new_value = old_value | *from;
   213       intptr_t res       = Atomic::cmpxchg_ptr(new_value, to, old_value);
   214       if (res == old_value) break;
   215     }
   216   }
   218   // the -1 is because we didn't advance them after the final CAS
   219   assert(from ==
   220            (intptr_t*) from_bitmap->word_addr(from_start_index) + word_num - 1,
   221             "invariant");
   222   assert(to == (intptr_t*) word_addr(to_start_index) + word_num - 1,
   223             "invariant");
   224 }
   226 void BitMap::at_put(idx_t offset, bool value) {
   227   if (value) {
   228     set_bit(offset);
   229   } else {
   230     clear_bit(offset);
   231   }
   232 }
   234 // Return true to indicate that this thread changed
   235 // the bit, false to indicate that someone else did.
   236 // In either case, the requested bit is in the
   237 // requested state some time during the period that
   238 // this thread is executing this call. More importantly,
   239 // if no other thread is executing an action to
   240 // change the requested bit to a state other than
   241 // the one that this thread is trying to set it to,
   242 // then the the bit is in the expected state
   243 // at exit from this method. However, rather than
   244 // make such a strong assertion here, based on
   245 // assuming such constrained use (which though true
   246 // today, could change in the future to service some
   247 // funky parallel algorithm), we encourage callers
   248 // to do such verification, as and when appropriate.
   249 bool BitMap::par_at_put(idx_t bit, bool value) {
   250   return value ? par_set_bit(bit) : par_clear_bit(bit);
   251 }
   253 void BitMap::at_put_grow(idx_t offset, bool value) {
   254   if (offset >= size()) {
   255     resize(2 * MAX2(size(), offset));
   256   }
   257   at_put(offset, value);
   258 }
   260 void BitMap::at_put_range(idx_t start_offset, idx_t end_offset, bool value) {
   261   if (value) {
   262     set_range(start_offset, end_offset);
   263   } else {
   264     clear_range(start_offset, end_offset);
   265   }
   266 }
   268 void BitMap::par_at_put_range(idx_t beg, idx_t end, bool value) {
   269   verify_range(beg, end);
   271   idx_t beg_full_word = word_index_round_up(beg);
   272   idx_t end_full_word = word_index(end);
   274   if (beg_full_word < end_full_word) {
   275     // The range includes at least one full word.
   276     par_put_range_within_word(beg, bit_index(beg_full_word), value);
   277     if (value) {
   278       set_range_of_words(beg_full_word, end_full_word);
   279     } else {
   280       clear_range_of_words(beg_full_word, end_full_word);
   281     }
   282     par_put_range_within_word(bit_index(end_full_word), end, value);
   283   } else {
   284     // The range spans at most 2 partial words.
   285     idx_t boundary = MIN2(bit_index(beg_full_word), end);
   286     par_put_range_within_word(beg, boundary, value);
   287     par_put_range_within_word(boundary, end, value);
   288   }
   290 }
   292 void BitMap::at_put_large_range(idx_t beg, idx_t end, bool value) {
   293   if (value) {
   294     set_large_range(beg, end);
   295   } else {
   296     clear_large_range(beg, end);
   297   }
   298 }
   300 void BitMap::par_at_put_large_range(idx_t beg, idx_t end, bool value) {
   301   verify_range(beg, end);
   303   idx_t beg_full_word = word_index_round_up(beg);
   304   idx_t end_full_word = word_index(end);
   306   assert(end_full_word - beg_full_word >= 32,
   307          "the range must include at least 32 bytes");
   309   // The range includes at least one full word.
   310   par_put_range_within_word(beg, bit_index(beg_full_word), value);
   311   if (value) {
   312     set_large_range_of_words(beg_full_word, end_full_word);
   313   } else {
   314     clear_large_range_of_words(beg_full_word, end_full_word);
   315   }
   316   par_put_range_within_word(bit_index(end_full_word), end, value);
   317 }
   319 bool BitMap::contains(const BitMap other) const {
   320   assert(size() == other.size(), "must have same size");
   321   bm_word_t* dest_map = map();
   322   bm_word_t* other_map = other.map();
   323   idx_t size = size_in_words();
   324   for (idx_t index = 0; index < size_in_words(); index++) {
   325     bm_word_t word_union = dest_map[index] | other_map[index];
   326     // If this has more bits set than dest_map[index], then other is not a
   327     // subset.
   328     if (word_union != dest_map[index]) return false;
   329   }
   330   return true;
   331 }
   333 bool BitMap::intersects(const BitMap other) const {
   334   assert(size() == other.size(), "must have same size");
   335   bm_word_t* dest_map = map();
   336   bm_word_t* other_map = other.map();
   337   idx_t size = size_in_words();
   338   for (idx_t index = 0; index < size_in_words(); index++) {
   339     if ((dest_map[index] & other_map[index]) != 0) return true;
   340   }
   341   // Otherwise, no intersection.
   342   return false;
   343 }
   345 void BitMap::set_union(BitMap other) {
   346   assert(size() == other.size(), "must have same size");
   347   bm_word_t* dest_map = map();
   348   bm_word_t* other_map = other.map();
   349   idx_t size = size_in_words();
   350   for (idx_t index = 0; index < size_in_words(); index++) {
   351     dest_map[index] = dest_map[index] | other_map[index];
   352   }
   353 }
   356 void BitMap::set_difference(BitMap other) {
   357   assert(size() == other.size(), "must have same size");
   358   bm_word_t* dest_map = map();
   359   bm_word_t* other_map = other.map();
   360   idx_t size = size_in_words();
   361   for (idx_t index = 0; index < size_in_words(); index++) {
   362     dest_map[index] = dest_map[index] & ~(other_map[index]);
   363   }
   364 }
   367 void BitMap::set_intersection(BitMap other) {
   368   assert(size() == other.size(), "must have same size");
   369   bm_word_t* dest_map = map();
   370   bm_word_t* other_map = other.map();
   371   idx_t size = size_in_words();
   372   for (idx_t index = 0; index < size; index++) {
   373     dest_map[index]  = dest_map[index] & other_map[index];
   374   }
   375 }
   378 void BitMap::set_intersection_at_offset(BitMap other, idx_t offset) {
   379   assert(other.size() >= offset, "offset not in range");
   380   assert(other.size() - offset >= size(), "other not large enough");
   381   // XXX Ideally, we would remove this restriction.
   382   guarantee((offset % (sizeof(bm_word_t) * BitsPerByte)) == 0,
   383             "Only handle aligned cases so far.");
   384   bm_word_t* dest_map = map();
   385   bm_word_t* other_map = other.map();
   386   idx_t offset_word_ind = word_index(offset);
   387   idx_t size = size_in_words();
   388   for (idx_t index = 0; index < size; index++) {
   389     dest_map[index] = dest_map[index] & other_map[offset_word_ind + index];
   390   }
   391 }
   393 bool BitMap::set_union_with_result(BitMap other) {
   394   assert(size() == other.size(), "must have same size");
   395   bool changed = false;
   396   bm_word_t* dest_map = map();
   397   bm_word_t* other_map = other.map();
   398   idx_t size = size_in_words();
   399   for (idx_t index = 0; index < size; index++) {
   400     idx_t temp = map(index) | other_map[index];
   401     changed = changed || (temp != map(index));
   402     map()[index] = temp;
   403   }
   404   return changed;
   405 }
   408 bool BitMap::set_difference_with_result(BitMap other) {
   409   assert(size() == other.size(), "must have same size");
   410   bool changed = false;
   411   bm_word_t* dest_map = map();
   412   bm_word_t* other_map = other.map();
   413   idx_t size = size_in_words();
   414   for (idx_t index = 0; index < size; index++) {
   415     bm_word_t temp = dest_map[index] & ~(other_map[index]);
   416     changed = changed || (temp != dest_map[index]);
   417     dest_map[index] = temp;
   418   }
   419   return changed;
   420 }
   423 bool BitMap::set_intersection_with_result(BitMap other) {
   424   assert(size() == other.size(), "must have same size");
   425   bool changed = false;
   426   bm_word_t* dest_map = map();
   427   bm_word_t* other_map = other.map();
   428   idx_t size = size_in_words();
   429   for (idx_t index = 0; index < size; index++) {
   430     bm_word_t orig = dest_map[index];
   431     bm_word_t temp = orig & other_map[index];
   432     changed = changed || (temp != orig);
   433     dest_map[index]  = temp;
   434   }
   435   return changed;
   436 }
   439 void BitMap::set_from(BitMap other) {
   440   assert(size() == other.size(), "must have same size");
   441   bm_word_t* dest_map = map();
   442   bm_word_t* other_map = other.map();
   443   idx_t size = size_in_words();
   444   for (idx_t index = 0; index < size; index++) {
   445     dest_map[index] = other_map[index];
   446   }
   447 }
   450 bool BitMap::is_same(BitMap other) {
   451   assert(size() == other.size(), "must have same size");
   452   bm_word_t* dest_map = map();
   453   bm_word_t* other_map = other.map();
   454   idx_t size = size_in_words();
   455   for (idx_t index = 0; index < size; index++) {
   456     if (dest_map[index] != other_map[index]) return false;
   457   }
   458   return true;
   459 }
   461 bool BitMap::is_full() const {
   462   bm_word_t* word = map();
   463   idx_t rest = size();
   464   for (; rest >= (idx_t) BitsPerWord; rest -= BitsPerWord) {
   465     if (*word != (bm_word_t) AllBits) return false;
   466     word++;
   467   }
   468   return rest == 0 || (*word | ~right_n_bits((int)rest)) == (bm_word_t) AllBits;
   469 }
   472 bool BitMap::is_empty() const {
   473   bm_word_t* word = map();
   474   idx_t rest = size();
   475   for (; rest >= (idx_t) BitsPerWord; rest -= BitsPerWord) {
   476     if (*word != (bm_word_t) NoBits) return false;
   477     word++;
   478   }
   479   return rest == 0 || (*word & right_n_bits((int)rest)) == (bm_word_t) NoBits;
   480 }
   482 void BitMap::clear_large() {
   483   clear_large_range_of_words(0, size_in_words());
   484 }
   486 // Note that if the closure itself modifies the bitmap
   487 // then modifications in and to the left of the _bit_ being
   488 // currently sampled will not be seen. Note also that the
   489 // interval [leftOffset, rightOffset) is right open.
   490 bool BitMap::iterate(BitMapClosure* blk, idx_t leftOffset, idx_t rightOffset) {
   491   verify_range(leftOffset, rightOffset);
   493   idx_t startIndex = word_index(leftOffset);
   494   idx_t endIndex   = MIN2(word_index(rightOffset) + 1, size_in_words());
   495   for (idx_t index = startIndex, offset = leftOffset;
   496        offset < rightOffset && index < endIndex;
   497        offset = (++index) << LogBitsPerWord) {
   498     idx_t rest = map(index) >> (offset & (BitsPerWord - 1));
   499     for (; offset < rightOffset && rest != (bm_word_t)NoBits; offset++) {
   500       if (rest & 1) {
   501         if (!blk->do_bit(offset)) return false;
   502         //  resample at each closure application
   503         // (see, for instance, CMS bug 4525989)
   504         rest = map(index) >> (offset & (BitsPerWord -1));
   505       }
   506       rest = rest >> 1;
   507     }
   508   }
   509   return true;
   510 }
   512 BitMap::idx_t* BitMap::_pop_count_table = NULL;
   514 void BitMap::init_pop_count_table() {
   515   if (_pop_count_table == NULL) {
   516     BitMap::idx_t *table = NEW_C_HEAP_ARRAY(idx_t, 256);
   517     for (uint i = 0; i < 256; i++) {
   518       table[i] = num_set_bits(i);
   519     }
   521     intptr_t res = Atomic::cmpxchg_ptr((intptr_t)  table,
   522                                        (intptr_t*) &_pop_count_table,
   523                                        (intptr_t)  NULL_WORD);
   524     if (res != NULL_WORD) {
   525       guarantee( _pop_count_table == (void*) res, "invariant" );
   526       FREE_C_HEAP_ARRAY(bm_word_t, table);
   527     }
   528   }
   529 }
   531 BitMap::idx_t BitMap::num_set_bits(bm_word_t w) {
   532   idx_t bits = 0;
   534   while (w != 0) {
   535     while ((w & 1) == 0) {
   536       w >>= 1;
   537     }
   538     bits++;
   539     w >>= 1;
   540   }
   541   return bits;
   542 }
   544 BitMap::idx_t BitMap::num_set_bits_from_table(unsigned char c) {
   545   assert(_pop_count_table != NULL, "precondition");
   546   return _pop_count_table[c];
   547 }
   549 BitMap::idx_t BitMap::count_one_bits() const {
   550   init_pop_count_table(); // If necessary.
   551   idx_t sum = 0;
   552   typedef unsigned char uchar;
   553   for (idx_t i = 0; i < size_in_words(); i++) {
   554     bm_word_t w = map()[i];
   555     for (size_t j = 0; j < sizeof(bm_word_t); j++) {
   556       sum += num_set_bits_from_table(uchar(w & 255));
   557       w >>= 8;
   558     }
   559   }
   560   return sum;
   561 }
   564 #ifndef PRODUCT
   566 void BitMap::print_on(outputStream* st) const {
   567   tty->print("Bitmap(%d):", size());
   568   for (idx_t index = 0; index < size(); index++) {
   569     tty->print("%c", at(index) ? '1' : '0');
   570   }
   571   tty->cr();
   572 }
   574 #endif
   577 BitMap2D::BitMap2D(bm_word_t* map, idx_t size_in_slots, idx_t bits_per_slot)
   578   : _bits_per_slot(bits_per_slot)
   579   , _map(map, size_in_slots * bits_per_slot)
   580 {
   581 }
   584 BitMap2D::BitMap2D(idx_t size_in_slots, idx_t bits_per_slot)
   585   : _bits_per_slot(bits_per_slot)
   586   , _map(size_in_slots * bits_per_slot)
   587 {
   588 }

mercurial