1 /*
   2  * Copyright (c) 2015, 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 
  25 // Concurrent marking bit map wrapper
  26 
  27 #include "gc/shared/cmBitMap.inline.hpp"
  28 #include "utilities/bitMap.inline.hpp"
  29 
  30 CMBitMapRO::CMBitMapRO(int shifter) :
  31   _bm(),
  32   _shifter(shifter) {
  33   _bmStartWord = 0;
  34   _bmWordSize = 0;
  35 }
  36 
  37 HeapWord* CMBitMapRO::getNextMarkedWordAddress(const HeapWord* addr,
  38                                                const HeapWord* limit) const {
  39   // First we must round addr *up* to a possible object boundary.
  40   addr = (HeapWord*)align_size_up((intptr_t)addr,
  41                                   HeapWordSize << _shifter);
  42   size_t addrOffset = heapWordToOffset(addr);
  43   if (limit == NULL) {
  44     limit = _bmStartWord + _bmWordSize;
  45   }
  46   size_t limitOffset = heapWordToOffset(limit);
  47   size_t nextOffset = _bm.get_next_one_offset(addrOffset, limitOffset);
  48   HeapWord* nextAddr = offsetToHeapWord(nextOffset);
  49   assert(nextAddr >= addr, "get_next_one postcondition");
  50   assert(nextAddr == limit || isMarked(nextAddr),
  51          "get_next_one postcondition");
  52   return nextAddr;
  53 }
  54 
  55 HeapWord* CMBitMapRO::getNextUnmarkedWordAddress(const HeapWord* addr,
  56                                                  const HeapWord* limit) const {
  57   size_t addrOffset = heapWordToOffset(addr);
  58   if (limit == NULL) {
  59     limit = _bmStartWord + _bmWordSize;
  60   }
  61   size_t limitOffset = heapWordToOffset(limit);
  62   size_t nextOffset = _bm.get_next_zero_offset(addrOffset, limitOffset);
  63   HeapWord* nextAddr = offsetToHeapWord(nextOffset);
  64   assert(nextAddr >= addr, "get_next_one postcondition");
  65   assert(nextAddr == limit || !isMarked(nextAddr),
  66          "get_next_one postcondition");
  67   return nextAddr;
  68 }
  69 
  70 int CMBitMapRO::heapWordDiffToOffsetDiff(size_t diff) const {
  71   assert((diff & ((1 << _shifter) - 1)) == 0, "argument check");
  72   return (int) (diff >> _shifter);
  73 }
  74 
  75 #ifndef PRODUCT
  76 bool CMBitMapRO::covers(MemRegion heap_rs) const {
  77   // assert(_bm.map() == _virtual_space.low(), "map inconsistency");
  78   assert(((size_t)_bm.size() * ((size_t)1 << _shifter)) == _bmWordSize,
  79          "size inconsistency");
  80   return _bmStartWord == (HeapWord*)(heap_rs.start()) &&
  81          _bmWordSize  == heap_rs.word_size();
  82 }
  83 #endif
  84 
  85 void CMBitMapRO::print_on_error(outputStream* st, const char* prefix) const {
  86   _bm.print_on_error(st, prefix);
  87 }
  88 
  89 size_t CMBitMap::compute_size(size_t heap_size) {
  90   return heap_size / mark_distance();
  91 }
  92 
  93 size_t CMBitMap::mark_distance() {
  94   return MinObjAlignmentInBytes * BitsPerByte;
  95 }
  96 
  97 void CMBitMap::initialize(MemRegion heap, MemRegion bitmap) {
  98   _bmStartWord = heap.start();
  99   _bmWordSize = heap.word_size();
 100 
 101   _bm.set_map((BitMap::bm_word_t*) bitmap.start());
 102   _bm.set_size(_bmWordSize >> _shifter);
 103 }
 104 
 105 void CMBitMap::clearAll() {
 106   _bm.clear();
 107 }
 108 
 109 void CMBitMap::markRange(MemRegion mr) {
 110   mr.intersection(MemRegion(_bmStartWord, _bmWordSize));
 111   assert(!mr.is_empty(), "unexpected empty region");
 112   assert((offsetToHeapWord(heapWordToOffset(mr.end())) ==
 113           ((HeapWord *) mr.end())),
 114          "markRange memory region end is not card aligned");
 115   // convert address range into offset range
 116   _bm.at_put_range(heapWordToOffset(mr.start()),
 117                    heapWordToOffset(mr.end()), true);
 118 }
 119 
 120 void CMBitMap::parMarkRange(MemRegion mr) {
 121   mr.intersection(MemRegion(_bmStartWord, _bmWordSize));
 122   assert(!mr.is_empty(), "unexpected empty region");
 123   assert((offsetToHeapWord(heapWordToOffset(mr.end())) ==
 124           ((HeapWord *) mr.end())),
 125          "markRange memory region end is not card aligned");
 126   // convert address range into offset range
 127   _bm.par_at_put_range(heapWordToOffset(mr.start()),
 128                    heapWordToOffset(mr.end()), true);
 129 }
 130 
 131 void CMBitMap::clearRange(MemRegion mr) {
 132   mr.intersection(MemRegion(_bmStartWord, _bmWordSize));
 133   assert(!mr.is_empty(), "unexpected empty region");
 134   // convert address range into offset range
 135   _bm.at_put_range(heapWordToOffset(mr.start()),
 136                    heapWordToOffset(mr.end()), false);
 137 }
 138 
 139 MemRegion CMBitMap::getAndClearMarkedRegion(HeapWord* addr,
 140                                             HeapWord* end_addr) {
 141   HeapWord* start = getNextMarkedWordAddress(addr);
 142   start = MIN2(start, end_addr);
 143   HeapWord* end   = getNextUnmarkedWordAddress(start);
 144   end = MIN2(end, end_addr);
 145   assert(start <= end, "Consistency check");
 146   MemRegion mr(start, end);
 147   if (!mr.is_empty()) {
 148     clearRange(mr);
 149   }
 150   return mr;
 151 }