1 /*
   2  * Copyright (c) 2013, 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 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1HEAPSPANNINGTABLE_HPP
  26 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1HEAPSPANNINGTABLE_HPP
  27 
  28 #include "memory/allocation.inline.hpp"
  29 
  30 // The G1HeapSpanningTable class is a utility class that provides
  31 // facilities to subclasses that divide the G1 heap into fixed size
  32 // chunks (e.g. heap regions) and use an array or arrays that have one
  33 // entry per such chunk. It provides methods that can retrieve an
  34 // array element given either an index or a heap address. For the case
  35 // where the given heap address is known to be valid (i.e., within the
  36 // G1 heap) a fast look-up is also provided (using a version of the
  37 // array pointer that is biased to address 0). The G1HeapSpanningTable
  38 // class keeps track of both the max length of the array as well as
  39 // which part of it is actively used.
  40 
  41 template <class T>
  42 class G1HeapSpanningTable :  public CHeapObj<mtGC> {
  43  protected:
  44   // Sub classes should override this.
  45   virtual T default_value() const = 0;
  46 
  47   // The address of the first reserved word in the heap.
  48   HeapWord* _heap_bottom;
  49 
  50   // The active bound of the heap, i.e., the address of the last
  51   // committed word in the heap + 1.
  52   HeapWord* _heap_end;
  53 
  54   // The maximum bound of the heap, i.e., the address of the last
  55   // reserved word in the heap + 1.
  56   HeapWord* _max_heap_end;
  57 
  58   // The active number of array elements.
  59   uint _length;
  60 
  61   // The maximum value _length has ever grown to.
  62   uint _length_high_watermark;
  63 
  64   // The max number of array elements.
  65   uint _max_length;
  66 
  67   // The log of the heap subdivision size in bytes.
  68   uint _shift_by;
  69 
  70   // Return the number of array elements for the given heap bound.
  71   uint length_for(HeapWord* end) {
  72     assert(_heap_bottom <= end && end <= _max_heap_end,
  73         err_msg("end: "PTR_FORMAT" bottom: "PTR_FORMAT" max end: "PTR_FORMAT, \
  74                 end, _heap_bottom, _max_heap_end));
  75     size_t diff_bytes = pointer_delta(end, _heap_bottom, sizeof(char));
  76     uint length = (uint) (diff_bytes >> _shift_by);
  77     assert(((size_t)(length << _shift_by)) == diff_bytes, "sanity");
  78     assert(length <= _max_length,
  79            err_msg("length: %u max length: %u", length, _max_length));
  80     return length;
  81   }
  82 
  83   // getters and setters with index
  84 
  85   // Return the element of the given array at the given index. Assume
  86   // the index is valid. This is a convenience method that does sanity
  87   // checking on the index.
  88   T get(T* array, uint index) const {
  89     assert(index < _length, err_msg("index: %u length: %u", index, _length));
  90     return array[index];
  91   }
  92 
  93   // Set the element of the given array at the given index to the
  94   // given value. Assume the index is valid. This is a convenience
  95   // method that does sanity checking on the index.
  96   void set(T* array, uint index, T value) {
  97     assert(index < _length, err_msg("index: %u length: %u", index, _length));
  98     array[index] = value;
  99   }
 100 
 101   // getters with address (normal and fast versions)
 102 
 103   // Map a heap address to a biased index. Assume that the address is valid.
 104   uintx addr_to_index_biased(HeapWord* addr) const {
 105     assert(_heap_bottom <= addr && addr < _max_heap_end,
 106            err_msg("addr: "PTR_FORMAT" bottom: "PTR_FORMAT" end: "PTR_FORMAT,
 107                    addr, _heap_bottom, _max_heap_end));
 108     return (uintx) addr >> _shift_by;
 109   }
 110 
 111   // Return the element of the given array that corresponds to the
 112   // given address. The array should be the biased version. Assume
 113   // that the address is valid.
 114   T get_unsafe(T* array_biased, HeapWord* addr) const {
 115     // No need to check the validity of addr as addr_to_index_biased()
 116     // will do so.
 117     uintx index_biased = addr_to_index_biased(addr);
 118     return array_biased[index_biased];
 119   }
 120 
 121   // Allocate, clear, and return a new array.
 122   T* create_new_array() { return (T*) create_new_array_base(); }
 123 
 124   // Return the biased (to address 0) address of the given array.
 125   T* get_biased_array(T* array) {
 126     T* array_biased = array - (uintx) ((uintptr_t) _heap_bottom >> _shift_by);
 127     assert(&array[0] == &array_biased[addr_to_index_biased(_heap_bottom)],
 128            "array slot 0 should be the same as as the biased slot for bottom");
 129     return array_biased;
 130   }
 131 
 132   // Set all elements of the given array to the default value.
 133   void clear(T* array) {
 134     for (uint i=0; i < max_length(); i += 1) {
 135       array[i] = default_value();
 136     }
 137   }
 138 
 139   // Allocate, clear, and return a new array.
 140   T* create_new_array_base() {
 141     T* array = (T*) NEW_C_HEAP_ARRAY(char, array_size_bytes(), mtGC);
 142     clear(array);
 143     return array;
 144   }
 145 
 146   // Size of the array in bytes.
 147   size_t array_size_bytes() {
 148     return (size_t) _max_length * sizeof(T);
 149   }
 150 
 151   // Update all fields to reflect that the heap end has been moved.
 152   // Return the previous heap end.
 153   HeapWord* update_heap_end(HeapWord* new_end) {
 154     HeapWord* old_heap_end = _heap_end;
 155     
 156     // length_for() will verify new_end so we don't have to do it here too.
 157     uint new_length = length_for(new_end);
 158     _length = new_length;
 159     if (new_length > _length_high_watermark) {
 160       _length_high_watermark = new_length;
 161     }
 162     _heap_end = new_end;
 163     
 164     return old_heap_end;
 165   }
 166 
 167   // Determine whether the address falls into the G1 heap or not.
 168   bool in_g1_heap(HeapWord* addr) const {
 169     assert(addr == NULL || addr >= _heap_bottom,
 170           err_msg("addr: "PTR_FORMAT" bottom: "PTR_FORMAT, addr, _heap_bottom));
 171     // We always check against _max_heap_end instead of_heap_end.
 172     // Sometimes we expand the heap during a GC concurrently
 173     // with other threads and this avoids any potential races.
 174     return addr != NULL && addr < _max_heap_end;
 175   }
 176 
 177   // Empty constructor, we'll do all initialization in the initialize() method.
 178   G1HeapSpanningTable() { }
 179 
 180   void initialize_base(HeapWord* bottom, HeapWord* max_end, uint shift_by) {
 181     _shift_by              = shift_by;
 182     
 183     _heap_bottom           = bottom;
 184     _heap_end              = bottom;
 185     _max_heap_end          = max_end;
 186     
 187     _length                = 0;
 188     _length_high_watermark = 0;
 189     _max_length            = length_for(max_end);
 190   }
 191 
 192 #ifndef PRODUCT  
 193   // Do sanity checking.
 194   void verify_optional() {
 195     uint length_for_heap_end = length_for(_heap_end);
 196     guarantee(length_for_heap_end == _length,
 197               err_msg("invariant: _length: %u _heap_end: "PTR_FORMAT" %u",
 198                       _length, _heap_end, length_for_heap_end));
 199     guarantee(_length <= _length_high_watermark,
 200               err_msg("invariant: _length: %u _length_high_watermark: %u",
 201                       _length, _length_high_watermark));
 202     guarantee(_length_high_watermark <= _max_length,
 203               err_msg("invariant: _length_high_watermark: %u _max_length: %u",
 204                       _length_high_watermark, _max_length));
 205   }
 206 #endif // !PRODUCT
 207 
 208  public:
 209   // Return the active number of array elements.
 210   uint length() const { return _length; }
 211 
 212   // Return the maximum number of array elements.
 213   uint max_length() const { return _max_length; }
 214 };
 215 
 216 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1HEAPSPANNINGTABLE_HPP