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

changeset 2713
02f49b66361a
parent 2646
04d1138b4cce
child 2716
c84ee870e0b9
     1.1 --- a/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp	Wed Mar 23 14:12:51 2011 +0100
     1.2 +++ b/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp	Mon Mar 28 10:58:54 2011 -0700
     1.3 @@ -31,19 +31,23 @@
     1.4  #include "gc_implementation/g1/heapRegionSeq.inline.hpp"
     1.5  #include "memory/space.inline.hpp"
     1.6  #include "runtime/atomic.hpp"
     1.7 +#include "runtime/java.hpp"
     1.8  #include "utilities/copy.hpp"
     1.9  
    1.10  // Possible sizes for the card counts cache: odd primes that roughly double in size.
    1.11  // (See jvmtiTagMap.cpp).
    1.12 -int ConcurrentG1Refine::_cc_cache_sizes[] = {
    1.13 -        16381,    32771,    76831,    150001,   307261,
    1.14 -       614563,  1228891,  2457733,   4915219,  9830479,
    1.15 -     19660831, 39321619, 78643219, 157286461,       -1
    1.16 +
    1.17 +#define MAX_SIZE ((size_t) -1)
    1.18 +
    1.19 +size_t ConcurrentG1Refine::_cc_cache_sizes[] = {
    1.20 +          16381,    32771,    76831,    150001,   307261,
    1.21 +         614563,  1228891,  2457733,   4915219,  9830479,
    1.22 +       19660831, 39321619, 78643219, 157286461,  MAX_SIZE
    1.23    };
    1.24  
    1.25  ConcurrentG1Refine::ConcurrentG1Refine() :
    1.26    _card_counts(NULL), _card_epochs(NULL),
    1.27 -  _n_card_counts(0), _max_n_card_counts(0),
    1.28 +  _n_card_counts(0), _max_cards(0), _max_n_card_counts(0),
    1.29    _cache_size_index(0), _expand_card_counts(false),
    1.30    _hot_cache(NULL),
    1.31    _def_use_cache(false), _use_cache(false),
    1.32 @@ -98,27 +102,44 @@
    1.33  void ConcurrentG1Refine::init() {
    1.34    if (G1ConcRSLogCacheSize > 0) {
    1.35      _g1h = G1CollectedHeap::heap();
    1.36 -    _max_n_card_counts =
    1.37 -      (unsigned) (_g1h->max_capacity() >> CardTableModRefBS::card_shift);
    1.38 +
    1.39 +    _max_cards = _g1h->max_capacity() >> CardTableModRefBS::card_shift;
    1.40 +    _max_n_card_counts = _max_cards * G1MaxHotCardCountSizePercent / 100;
    1.41  
    1.42      size_t max_card_num = ((size_t)1 << (sizeof(unsigned)*BitsPerByte-1)) - 1;
    1.43 -    guarantee(_max_n_card_counts < max_card_num, "card_num representation");
    1.44 +    guarantee(_max_cards < max_card_num, "card_num representation");
    1.45  
    1.46 -    int desired = _max_n_card_counts / InitialCacheFraction;
    1.47 -    for (_cache_size_index = 0;
    1.48 -              _cc_cache_sizes[_cache_size_index] >= 0; _cache_size_index++) {
    1.49 -      if (_cc_cache_sizes[_cache_size_index] >= desired) break;
    1.50 +    // We need _n_card_counts to be less than _max_n_card_counts here
    1.51 +    // so that the expansion call (below) actually allocates the
    1.52 +    // _counts and _epochs arrays.
    1.53 +    assert(_n_card_counts == 0, "pre-condition");
    1.54 +    assert(_max_n_card_counts > 0, "pre-condition");
    1.55 +
    1.56 +    // Find the index into cache size array that is of a size that's
    1.57 +    // large enough to hold desired_sz.
    1.58 +    size_t desired_sz = _max_cards / InitialCacheFraction;
    1.59 +    int desired_sz_index = 0;
    1.60 +    while (_cc_cache_sizes[desired_sz_index] < desired_sz) {
    1.61 +      desired_sz_index += 1;
    1.62 +      assert(desired_sz_index <  MAX_CC_CACHE_INDEX, "invariant");
    1.63      }
    1.64 -    _cache_size_index = MAX2(0, (_cache_size_index - 1));
    1.65 +    assert(desired_sz_index <  MAX_CC_CACHE_INDEX, "invariant");
    1.66  
    1.67 -    int initial_size = _cc_cache_sizes[_cache_size_index];
    1.68 -    if (initial_size < 0) initial_size = _max_n_card_counts;
    1.69 +    // If the desired_sz value is between two sizes then
    1.70 +    // _cc_cache_sizes[desired_sz_index-1] < desired_sz <= _cc_cache_sizes[desired_sz_index]
    1.71 +    // we will start with the lower size in the optimistic expectation that
    1.72 +    // we will not need to expand up. Note desired_sz_index could also be 0.
    1.73 +    if (desired_sz_index > 0 &&
    1.74 +        _cc_cache_sizes[desired_sz_index] > desired_sz) {
    1.75 +      desired_sz_index -= 1;
    1.76 +    }
    1.77  
    1.78 -    // Make sure we don't go bigger than we will ever need
    1.79 -    _n_card_counts = MIN2((unsigned) initial_size, _max_n_card_counts);
    1.80 -
    1.81 -    _card_counts = NEW_C_HEAP_ARRAY(CardCountCacheEntry, _n_card_counts);
    1.82 -    _card_epochs = NEW_C_HEAP_ARRAY(CardEpochCacheEntry, _n_card_counts);
    1.83 +    if (!expand_card_count_cache(desired_sz_index)) {
    1.84 +      // Allocation was unsuccessful - exit
    1.85 +      vm_exit_during_initialization("Could not reserve enough space for card count cache");
    1.86 +    }
    1.87 +    assert(_n_card_counts > 0, "post-condition");
    1.88 +    assert(_cache_size_index == desired_sz_index, "post-condition");
    1.89  
    1.90      Copy::fill_to_bytes(&_card_counts[0],
    1.91                          _n_card_counts * sizeof(CardCountCacheEntry));
    1.92 @@ -163,10 +184,13 @@
    1.93  
    1.94  ConcurrentG1Refine::~ConcurrentG1Refine() {
    1.95    if (G1ConcRSLogCacheSize > 0) {
    1.96 +    // Please see the comment in allocate_card_count_cache
    1.97 +    // for why we call os::malloc() and os::free() directly.
    1.98      assert(_card_counts != NULL, "Logic");
    1.99 -    FREE_C_HEAP_ARRAY(CardCountCacheEntry, _card_counts);
   1.100 +    os::free(_card_counts);
   1.101      assert(_card_epochs != NULL, "Logic");
   1.102 -    FREE_C_HEAP_ARRAY(CardEpochCacheEntry, _card_epochs);
   1.103 +    os::free(_card_epochs);
   1.104 +
   1.105      assert(_hot_cache != NULL, "Logic");
   1.106      FREE_C_HEAP_ARRAY(jbyte*, _hot_cache);
   1.107    }
   1.108 @@ -382,29 +406,93 @@
   1.109    }
   1.110  }
   1.111  
   1.112 -void ConcurrentG1Refine::expand_card_count_cache() {
   1.113 +// The arrays used to hold the card counts and the epochs must have
   1.114 +// a 1:1 correspondence. Hence they are allocated and freed together
   1.115 +// Returns true if the allocations of both the counts and epochs
   1.116 +// were successful; false otherwise.
   1.117 +bool ConcurrentG1Refine::allocate_card_count_cache(size_t n,
   1.118 +                                                   CardCountCacheEntry** counts,
   1.119 +                                                   CardEpochCacheEntry** epochs) {
   1.120 +  // We call the allocation/free routines directly for the counts
   1.121 +  // and epochs arrays. The NEW_C_HEAP_ARRAY/FREE_C_HEAP_ARRAY
   1.122 +  // macros call AllocateHeap and FreeHeap respectively.
   1.123 +  // AllocateHeap will call vm_exit_out_of_memory in the event
   1.124 +  // of an allocation failure and abort the JVM. With the
   1.125 +  // _counts/epochs arrays we only need to abort the JVM if the
   1.126 +  // initial allocation of these arrays fails.
   1.127 +  //
   1.128 +  // Additionally AllocateHeap/FreeHeap do some tracing of
   1.129 +  // allocate/free calls so calling one without calling the
   1.130 +  // other can cause inconsistencies in the tracing. So we
   1.131 +  // call neither.
   1.132 +
   1.133 +  assert(*counts == NULL, "out param");
   1.134 +  assert(*epochs == NULL, "out param");
   1.135 +
   1.136 +  size_t counts_size = n * sizeof(CardCountCacheEntry);
   1.137 +  size_t epochs_size = n * sizeof(CardEpochCacheEntry);
   1.138 +
   1.139 +  *counts = (CardCountCacheEntry*) os::malloc(counts_size);
   1.140 +  if (*counts == NULL) {
   1.141 +    // allocation was unsuccessful
   1.142 +    return false;
   1.143 +  }
   1.144 +
   1.145 +  *epochs = (CardEpochCacheEntry*) os::malloc(epochs_size);
   1.146 +  if (*epochs == NULL) {
   1.147 +    // allocation was unsuccessful - free counts array
   1.148 +    assert(*counts != NULL, "must be");
   1.149 +    os::free(*counts);
   1.150 +    *counts = NULL;
   1.151 +    return false;
   1.152 +  }
   1.153 +
   1.154 +  // We successfully allocated both counts and epochs
   1.155 +  return true;
   1.156 +}
   1.157 +
   1.158 +// Returns true if the card counts/epochs cache was
   1.159 +// successfully expanded; false otherwise.
   1.160 +bool ConcurrentG1Refine::expand_card_count_cache(int cache_size_idx) {
   1.161 +  // Can we expand the card count and epoch tables?
   1.162    if (_n_card_counts < _max_n_card_counts) {
   1.163 -    int new_idx = _cache_size_index+1;
   1.164 -    int new_size = _cc_cache_sizes[new_idx];
   1.165 -    if (new_size < 0) new_size = _max_n_card_counts;
   1.166 +    assert(cache_size_idx >= 0 && cache_size_idx  < MAX_CC_CACHE_INDEX, "oob");
   1.167  
   1.168 +    size_t cache_size = _cc_cache_sizes[cache_size_idx];
   1.169      // Make sure we don't go bigger than we will ever need
   1.170 -    new_size = MIN2((unsigned) new_size, _max_n_card_counts);
   1.171 +    cache_size = MIN2(cache_size, _max_n_card_counts);
   1.172  
   1.173 -    // Expand the card count and card epoch tables
   1.174 -    if (new_size > (int)_n_card_counts) {
   1.175 -      // We can just free and allocate a new array as we're
   1.176 -      // not interested in preserving the contents
   1.177 -      assert(_card_counts != NULL, "Logic!");
   1.178 -      assert(_card_epochs != NULL, "Logic!");
   1.179 -      FREE_C_HEAP_ARRAY(CardCountCacheEntry, _card_counts);
   1.180 -      FREE_C_HEAP_ARRAY(CardEpochCacheEntry, _card_epochs);
   1.181 -      _n_card_counts = new_size;
   1.182 -      _card_counts = NEW_C_HEAP_ARRAY(CardCountCacheEntry, _n_card_counts);
   1.183 -      _card_epochs = NEW_C_HEAP_ARRAY(CardEpochCacheEntry, _n_card_counts);
   1.184 -      _cache_size_index = new_idx;
   1.185 +    // Should we expand the card count and card epoch tables?
   1.186 +    if (cache_size > _n_card_counts) {
   1.187 +      // We have been asked to allocate new, larger, arrays for
   1.188 +      // the card counts and the epochs. Attempt the allocation
   1.189 +      // of both before we free the existing arrays in case
   1.190 +      // the allocation is unsuccessful...
   1.191 +      CardCountCacheEntry* counts = NULL;
   1.192 +      CardEpochCacheEntry* epochs = NULL;
   1.193 +
   1.194 +      if (allocate_card_count_cache(cache_size, &counts, &epochs)) {
   1.195 +        // Allocation was successful.
   1.196 +        // We can just free the old arrays; we're
   1.197 +        // not interested in preserving the contents
   1.198 +        if (_card_counts != NULL) os::free(_card_counts);
   1.199 +        if (_card_epochs != NULL) os::free(_card_epochs);
   1.200 +
   1.201 +        // Cache the size of the arrays and the index that got us there.
   1.202 +        _n_card_counts = cache_size;
   1.203 +        _cache_size_index = cache_size_idx;
   1.204 +
   1.205 +        _card_counts = counts;
   1.206 +        _card_epochs = epochs;
   1.207 +
   1.208 +        // We successfully allocated/expanded the caches.
   1.209 +        return true;
   1.210 +      }
   1.211      }
   1.212    }
   1.213 +
   1.214 +  // We did not successfully expand the caches.
   1.215 +  return false;
   1.216  }
   1.217  
   1.218  void ConcurrentG1Refine::clear_and_record_card_counts() {
   1.219 @@ -415,10 +503,16 @@
   1.220  #endif
   1.221  
   1.222    if (_expand_card_counts) {
   1.223 -    expand_card_count_cache();
   1.224 +    int new_idx = _cache_size_index + 1;
   1.225 +
   1.226 +    if (expand_card_count_cache(new_idx)) {
   1.227 +      // Allocation was successful and  _n_card_counts has
   1.228 +      // been updated to the new size. We only need to clear
   1.229 +      // the epochs so we don't read a bogus epoch value
   1.230 +      // when inserting a card into the hot card cache.
   1.231 +      Copy::fill_to_bytes(&_card_epochs[0], _n_card_counts * sizeof(CardEpochCacheEntry));
   1.232 +    }
   1.233      _expand_card_counts = false;
   1.234 -    // Only need to clear the epochs.
   1.235 -    Copy::fill_to_bytes(&_card_epochs[0], _n_card_counts * sizeof(CardEpochCacheEntry));
   1.236    }
   1.237  
   1.238    int this_epoch = (int) _n_periods;

mercurial