src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp

Print this page
rev 6802 : imported patch refactor-heapregionseq
rev 6804 : imported patch commit-uncommit-within-heap
rev 6805 : imported patch mikael-suggestions
rev 6806 : [mq]: bengt-suggestions


  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 #include "precompiled.hpp"
  26 #include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp"
  27 #include "gc_implementation/g1/heapRegion.hpp"
  28 #include "memory/space.hpp"
  29 #include "oops/oop.inline.hpp"
  30 #include "runtime/java.hpp"
  31 #include "services/memTracker.hpp"
  32 
  33 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
  34 







  35 //////////////////////////////////////////////////////////////////////
  36 // G1BlockOffsetSharedArray
  37 //////////////////////////////////////////////////////////////////////
  38 
  39 G1BlockOffsetSharedArray::G1BlockOffsetSharedArray(MemRegion reserved,
  40                                                    size_t init_word_size) :
  41   _reserved(reserved), _end(NULL)
  42 {
  43   size_t size = compute_size(reserved.word_size());
  44   ReservedSpace rs(ReservedSpace::allocation_align_size_up(size));
  45   if (!rs.is_reserved()) {
  46     vm_exit_during_initialization("Could not reserve enough space for heap offset array");
  47   }
  48   if (!_vs.initialize(rs, 0)) {
  49     vm_exit_during_initialization("Could not reserve enough space for heap offset array");
  50   }
  51 
  52   MemTracker::record_virtual_memory_type((address)rs.base(), mtGC);








  53 
  54   _offset_array = (u_char*)_vs.low_boundary();
  55   resize(init_word_size);
  56   if (TraceBlockOffsetTable) {
  57     gclog_or_tty->print_cr("G1BlockOffsetSharedArray::G1BlockOffsetSharedArray: ");
  58     gclog_or_tty->print_cr("  "
  59                   "  rs.base(): " INTPTR_FORMAT
  60                   "  rs.size(): " INTPTR_FORMAT
  61                   "  rs end(): " INTPTR_FORMAT,
  62                   rs.base(), rs.size(), rs.base() + rs.size());
  63     gclog_or_tty->print_cr("  "
  64                   "  _vs.low_boundary(): " INTPTR_FORMAT
  65                   "  _vs.high_boundary(): " INTPTR_FORMAT,
  66                   _vs.low_boundary(),
  67                   _vs.high_boundary());
  68   }
  69 }
  70 
  71 void G1BlockOffsetSharedArray::resize(size_t new_word_size) {
  72   assert(new_word_size <= _reserved.word_size(), "Resize larger than reserved");
  73   size_t new_size = compute_size(new_word_size);
  74   size_t old_size = _vs.committed_size();
  75   size_t delta;
  76   char* high = _vs.high();
  77   _end = _reserved.start() + new_word_size;
  78   if (new_size > old_size) {
  79     delta = ReservedSpace::page_align_size_up(new_size - old_size);
  80     assert(delta > 0, "just checking");
  81     if (!_vs.expand_by(delta)) {
  82       // Do better than this for Merlin
  83       vm_exit_out_of_memory(delta, OOM_MMAP_ERROR, "offset table expansion");
  84     }
  85     assert(_vs.high() == high + delta, "invalid expansion");
  86     // Initialization of the contents is left to the
  87     // G1BlockOffsetArray that uses it.
  88   } else {
  89     delta = ReservedSpace::page_align_size_down(old_size - new_size);
  90     if (delta == 0) return;
  91     _vs.shrink_by(delta);
  92     assert(_vs.high() == high - delta, "invalid expansion");
  93   }
  94 }
  95 
  96 bool G1BlockOffsetSharedArray::is_card_boundary(HeapWord* p) const {
  97   assert(p >= _reserved.start(), "just checking");
  98   size_t delta = pointer_delta(p, _reserved.start());
  99   return (delta & right_n_bits(LogN_words)) == (size_t)NoBits;
 100 }
 101 
 102 void G1BlockOffsetSharedArray::set_offset_array(HeapWord* left, HeapWord* right, u_char offset) {
 103   check_index(index_for(right - 1), "right address out of range");
 104   assert(left  < right, "Heap addresses out of order");
 105   size_t num_cards = pointer_delta(right, left) >> LogN_words;
 106   if (UseMemSetInBOT) {
 107     memset(&_offset_array[index_for(left)], offset, num_cards);
 108   } else {
 109     size_t i = index_for(left);
 110     const size_t end = i + num_cards;
 111     for (; i < end; i++) {
 112       _offset_array[i] = offset;
 113     }
 114   }
 115 }
 116 
 117 //////////////////////////////////////////////////////////////////////
 118 // G1BlockOffsetArray
 119 //////////////////////////////////////////////////////////////////////
 120 
 121 G1BlockOffsetArray::G1BlockOffsetArray(G1BlockOffsetSharedArray* array,
 122                                        MemRegion mr, bool init_to_zero) :
 123   G1BlockOffsetTable(mr.start(), mr.end()),
 124   _unallocated_block(_bottom),
 125   _array(array), _gsp(NULL),
 126   _init_to_zero(init_to_zero) {
 127   assert(_bottom <= _end, "arguments out of order");
 128   if (!_init_to_zero) {
 129     // initialize cards to point back to mr.start()
 130     set_remainder_to_point_to_start(mr.start() + N_words, mr.end());
 131     _array->set_offset_array(0, 0);  // set first card to 0
 132   }
 133 }
 134 


 631   return forward_to_block_containing_addr(q, addr);
 632 }
 633 
 634 HeapWord*
 635 G1BlockOffsetArrayContigSpace::
 636 block_start_unsafe_const(const void* addr) const {
 637   assert(_bottom <= addr && addr < _end,
 638          "addr must be covered by this Array");
 639   HeapWord* q = block_at_or_preceding(addr, true, _next_offset_index-1);
 640   HeapWord* n = q + block_size(q);
 641   return forward_to_block_containing_addr_const(q, n, addr);
 642 }
 643 
 644 G1BlockOffsetArrayContigSpace::
 645 G1BlockOffsetArrayContigSpace(G1BlockOffsetSharedArray* array,
 646                               MemRegion mr) :
 647   G1BlockOffsetArray(array, mr, true)
 648 {
 649   _next_offset_threshold = NULL;
 650   _next_offset_index = 0;



















 651 }
 652 
 653 HeapWord* G1BlockOffsetArrayContigSpace::initialize_threshold() {
 654   assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
 655          "just checking");
 656   _next_offset_index = _array->index_for(_bottom);
 657   _next_offset_index++;
 658   _next_offset_threshold =
 659     _array->address_for_index(_next_offset_index);
 660   return _next_offset_threshold;
 661 }
 662 
 663 void G1BlockOffsetArrayContigSpace::zero_bottom_entry() {
 664   assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
 665          "just checking");
 666   size_t bottom_index = _array->index_for(_bottom);
 667   assert(_array->address_for_index(bottom_index) == _bottom,
 668          "Precondition of call");
 669   _array->set_offset_array(bottom_index, 0);
 670 }


  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 #include "precompiled.hpp"
  26 #include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp"
  27 #include "gc_implementation/g1/heapRegion.hpp"
  28 #include "memory/space.hpp"
  29 #include "oops/oop.inline.hpp"
  30 #include "runtime/java.hpp"
  31 #include "services/memTracker.hpp"
  32 
  33 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
  34 
  35 void G1BlockOffsetSharedArrayMappingChangedListener::on_commit(uint start_idx, size_t num_regions) {
  36   // Nothing to do. The BOT is hard-wired to be part of the HeapRegion, and we cannot
  37   // retrieve it here since this would cause firing of several asserts. The code
  38   // exacuted after commit of a region already needs to do some re-initialization of
  39   // the HeapRegion, so we combine that.
  40 }
  41 
  42 //////////////////////////////////////////////////////////////////////
  43 // G1BlockOffsetSharedArray
  44 //////////////////////////////////////////////////////////////////////
  45 
  46 G1BlockOffsetSharedArray::G1BlockOffsetSharedArray(MemRegion heap, G1RegionToSpaceMapper* storage) :
  47   _reserved(), _end(NULL), _listener(), _offset_array(NULL) {










  48 
  49   _reserved = heap;
  50   _end = NULL;
  51 
  52   MemRegion bot_reserved = storage->reserved();
  53 
  54   _offset_array = (u_char*)bot_reserved.start();
  55   _end = _reserved.end();
  56 
  57   storage->set_mapping_changed_listener(&_listener);
  58   


  59   if (TraceBlockOffsetTable) {
  60     gclog_or_tty->print_cr("G1BlockOffsetSharedArray::G1BlockOffsetSharedArray: ");
  61     gclog_or_tty->print_cr("  "
  62                   "  rs.base(): " INTPTR_FORMAT
  63                   "  rs.size(): " INTPTR_FORMAT
  64                   "  rs end(): " INTPTR_FORMAT,
  65                   bot_reserved.start(), bot_reserved.byte_size(), bot_reserved.end());






























  66   }
  67 }
  68 
  69 bool G1BlockOffsetSharedArray::is_card_boundary(HeapWord* p) const {
  70   assert(p >= _reserved.start(), "just checking");
  71   size_t delta = pointer_delta(p, _reserved.start());
  72   return (delta & right_n_bits(LogN_words)) == (size_t)NoBits;
  73 }
  74 
  75 void G1BlockOffsetSharedArray::set_offset_array(HeapWord* left, HeapWord* right, u_char offset) {
  76   set_offset_array(index_for(left), index_for(right -1), offset);











  77 }
  78 
  79 //////////////////////////////////////////////////////////////////////
  80 // G1BlockOffsetArray
  81 //////////////////////////////////////////////////////////////////////
  82 
  83 G1BlockOffsetArray::G1BlockOffsetArray(G1BlockOffsetSharedArray* array,
  84                                        MemRegion mr, bool init_to_zero) :
  85   G1BlockOffsetTable(mr.start(), mr.end()),
  86   _unallocated_block(_bottom),
  87   _array(array), _gsp(NULL),
  88   _init_to_zero(init_to_zero) {
  89   assert(_bottom <= _end, "arguments out of order");
  90   if (!_init_to_zero) {
  91     // initialize cards to point back to mr.start()
  92     set_remainder_to_point_to_start(mr.start() + N_words, mr.end());
  93     _array->set_offset_array(0, 0);  // set first card to 0
  94   }
  95 }
  96 


 593   return forward_to_block_containing_addr(q, addr);
 594 }
 595 
 596 HeapWord*
 597 G1BlockOffsetArrayContigSpace::
 598 block_start_unsafe_const(const void* addr) const {
 599   assert(_bottom <= addr && addr < _end,
 600          "addr must be covered by this Array");
 601   HeapWord* q = block_at_or_preceding(addr, true, _next_offset_index-1);
 602   HeapWord* n = q + block_size(q);
 603   return forward_to_block_containing_addr_const(q, n, addr);
 604 }
 605 
 606 G1BlockOffsetArrayContigSpace::
 607 G1BlockOffsetArrayContigSpace(G1BlockOffsetSharedArray* array,
 608                               MemRegion mr) :
 609   G1BlockOffsetArray(array, mr, true)
 610 {
 611   _next_offset_threshold = NULL;
 612   _next_offset_index = 0;
 613 }
 614 
 615 HeapWord* G1BlockOffsetArrayContigSpace::initialize_threshold_raw() {
 616   assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
 617          "just checking");
 618   _next_offset_index = _array->index_for_raw(_bottom);
 619   _next_offset_index++;
 620   _next_offset_threshold =
 621     _array->address_for_index_raw(_next_offset_index);
 622   return _next_offset_threshold;
 623 }
 624 
 625 void G1BlockOffsetArrayContigSpace::zero_bottom_entry_raw() {
 626   assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
 627          "just checking");
 628   size_t bottom_index = _array->index_for_raw(_bottom);
 629   assert(_array->address_for_index_raw(bottom_index) == _bottom,
 630          "Precondition of call");
 631   _array->set_offset_array_raw(bottom_index, 0);
 632 }
 633 
 634 HeapWord* G1BlockOffsetArrayContigSpace::initialize_threshold() {
 635   assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
 636          "just checking");
 637   _next_offset_index = _array->index_for(_bottom);
 638   _next_offset_index++;
 639   _next_offset_threshold =
 640     _array->address_for_index(_next_offset_index);
 641   return _next_offset_threshold;
 642 }
 643 
 644 void G1BlockOffsetArrayContigSpace::zero_bottom_entry() {
 645   assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
 646          "just checking");
 647   size_t bottom_index = _array->index_for(_bottom);
 648   assert(_array->address_for_index(bottom_index) == _bottom,
 649          "Precondition of call");
 650   _array->set_offset_array(bottom_index, 0);
 651 }