concurrentG1Refine.hpp 8.2 KB
Newer Older
1
/*
2
 * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
19 20 21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
22 23 24
 *
 */

25 26 27 28 29 30 31 32
#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTG1REFINE_HPP
#define SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTG1REFINE_HPP

#include "memory/allocation.hpp"
#include "memory/cardTableModRefBS.hpp"
#include "runtime/thread.hpp"
#include "utilities/globalDefinitions.hpp"

33 34 35 36
// Forward decl
class ConcurrentG1RefineThread;
class G1RemSet;

37
class ConcurrentG1Refine: public CHeapObj {
38 39
  ConcurrentG1RefineThread** _threads;
  int _n_threads;
40 41 42 43 44 45 46 47 48 49
  int _n_worker_threads;
 /*
  * The value of the update buffer queue length falls into one of 3 zones:
  * green, yellow, red. If the value is in [0, green) nothing is
  * done, the buffers are left unprocessed to enable the caching effect of the
  * dirtied cards. In the yellow zone [green, yellow) the concurrent refinement
  * threads are gradually activated. In [yellow, red) all threads are
  * running. If the length becomes red (max queue length) the mutators start
  * processing the buffers.
  *
50 51
  * There are some interesting cases (when G1UseAdaptiveConcRefinement
  * is turned off):
52 53 54 55 56 57 58 59 60 61 62 63 64 65
  * 1) green = yellow = red = 0. In this case the mutator will process all
  *    buffers. Except for those that are created by the deferred updates
  *    machinery during a collection.
  * 2) green = 0. Means no caching. Can be a good way to minimize the
  *    amount of time spent updating rsets during a collection.
  */
  int _green_zone;
  int _yellow_zone;
  int _red_zone;

  int _thread_threshold_step;

  // Reset the threshold step value based of the current zone boundaries.
  void reset_threshold_step();
66

67
  // The cache for card refinement.
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
  bool   _use_cache;
  bool   _def_use_cache;

  size_t _n_periods;    // Used as clearing epoch

  // An evicting cache of the number of times each card
  // is accessed. Reduces, but does not eliminate, the amount
  // of duplicated processing of dirty cards.

  enum SomePrivateConstants {
    epoch_bits           = 32,
    card_num_shift       = epoch_bits,
    epoch_mask           = AllBits,
    card_num_mask        = AllBits,

    // The initial cache size is approximately this fraction
    // of a maximal cache (i.e. the size needed for all cards
    // in the heap)
    InitialCacheFraction = 512
  };

  const static julong card_num_mask_in_place =
                        (julong) card_num_mask << card_num_shift;

  typedef struct {
    julong _value;      // |  card_num   |  epoch   |
  } CardEpochCacheEntry;

  julong make_epoch_entry(unsigned int card_num, unsigned int epoch) {
97
    assert(0 <= card_num && card_num < _max_cards, "Bounds");
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
    assert(0 <= epoch && epoch <= _n_periods, "must be");

    return ((julong) card_num << card_num_shift) | epoch;
  }

  unsigned int extract_epoch(julong v) {
    return (v & epoch_mask);
  }

  unsigned int extract_card_num(julong v) {
    return (v & card_num_mask_in_place) >> card_num_shift;
  }

  typedef struct {
    unsigned char _count;
    unsigned char _evict_count;
  } CardCountCacheEntry;

  CardCountCacheEntry* _card_counts;
  CardEpochCacheEntry* _card_epochs;

  // The current number of buckets in the card count cache
120
  size_t _n_card_counts;
121

122 123 124 125 126 127 128 129
  // The number of cards for the entire reserved heap
  size_t _max_cards;

  // The max number of buckets for the card counts and epochs caches.
  // This is the maximum that the counts and epochs will grow to.
  // It is specified as a fraction or percentage of _max_cards using
  // G1MaxHotCardCountSizePercent.
  size_t _max_n_card_counts;
130 131 132

  // Possible sizes of the cache: odd primes that roughly double in size.
  // (See jvmtiTagMap.cpp).
133 134 135 136 137
  enum {
    MAX_CC_CACHE_INDEX = 15    // maximum index into the cache size array.
  };

  static size_t _cc_cache_sizes[MAX_CC_CACHE_INDEX];
138 139 140 141 142 143 144 145

  // The index in _cc_cache_sizes corresponding to the size of
  // _card_counts.
  int _cache_size_index;

  bool _expand_card_counts;

  const jbyte* _ct_bot;
146 147 148 149 150 151 152 153

  jbyte**      _hot_cache;
  int          _hot_cache_size;
  int          _n_hot;
  int          _hot_cache_idx;

  int          _hot_cache_par_chunk_size;
  volatile int _hot_cache_par_claimed_idx;
154

155 156 157 158
  // Needed to workaround 6817995
  CardTableModRefBS* _ct_bs;
  G1CollectedHeap*   _g1h;

159 160 161 162 163 164 165 166 167 168 169 170 171
  // Helper routine for expand_card_count_cache().
  // The arrays used to hold the card counts and the epochs must have
  // a 1:1 correspondence. Hence they are allocated and freed together.
  // Returns true if the allocations of both the counts and epochs
  // were successful; false otherwise.
  bool allocate_card_count_cache(size_t n,
                                 CardCountCacheEntry** counts,
                                 CardEpochCacheEntry** epochs);

  // Expands the arrays that hold the card counts and epochs
  // to the cache size at index. Returns true if the expansion/
  // allocation was successful; false otherwise.
  bool expand_card_count_cache(int index);
172 173

  // hash a given key (index of card_ptr) with the specified size
174
  static unsigned int hash(size_t key, size_t size) {
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
    return (unsigned int) key % size;
  }

  // hash a given key (index of card_ptr)
  unsigned int hash(size_t key) {
    return hash(key, _n_card_counts);
  }

  unsigned ptr_2_card_num(jbyte* card_ptr) {
    return (unsigned) (card_ptr - _ct_bot);
  }

  jbyte* card_num_2_ptr(unsigned card_num) {
    return (jbyte*) (_ct_bot + card_num);
  }

191
  // Returns the count of this card after incrementing it.
192 193 194 195
  jbyte* add_card_count(jbyte* card_ptr, int* count, bool* defer);

  // Returns true if this card is in a young region
  bool is_young_card(jbyte* card_ptr);
196 197 198 199 200 201

 public:
  ConcurrentG1Refine();
  ~ConcurrentG1Refine();

  void init(); // Accomplish some initialization that has to wait.
202
  void stop();
203

204 205
  void reinitialize_threads();

206 207
  // Iterate over the conc refine threads
  void threads_do(ThreadClosure *tc);
208 209 210 211

  // If this is the first entry for the slot, writes into the cache and
  // returns NULL.  If it causes an eviction, returns the evicted pointer.
  // Otherwise, its a cache hit, and returns NULL.
212
  jbyte* cache_insert(jbyte* card_ptr, bool* defer);
213 214

  // Process the cached entries.
J
johnc 已提交
215
  void clean_up_cache(int worker_i, G1RemSet* g1rs, DirtyCardQueue* into_cset_dcq);
216

217 218 219 220 221
  // Set up for parallel processing of the cards in the hot cache
  void clear_hot_cache_claimed_index() {
    _hot_cache_par_claimed_idx = 0;
  }

222 223 224 225 226 227 228 229 230 231 232 233 234 235
  // Discard entries in the hot cache.
  void clear_hot_cache() {
    _hot_cache_idx = 0; _n_hot = 0;
  }

  bool hot_cache_is_empty() { return _n_hot == 0; }

  bool use_cache() { return _use_cache; }
  void set_use_cache(bool b) {
    if (b) _use_cache = _def_use_cache;
    else   _use_cache = false;
  }

  void clear_and_record_card_counts();
236

237
  static int thread_num();
T
tonyp 已提交
238 239

  void print_worker_threads_on(outputStream* st) const;
240 241 242 243 244 245 246 247 248 249 250 251 252

  void set_green_zone(int x)  { _green_zone = x;  }
  void set_yellow_zone(int x) { _yellow_zone = x; }
  void set_red_zone(int x)    { _red_zone = x;    }

  int green_zone() const      { return _green_zone;  }
  int yellow_zone() const     { return _yellow_zone; }
  int red_zone() const        { return _red_zone;    }

  int total_thread_num() const  { return _n_threads;        }
  int worker_thread_num() const { return _n_worker_threads; }

  int thread_threshold_step() const { return _thread_threshold_step; }
253
};
254 255

#endif // SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTG1REFINE_HPP