annotate src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp @ 2034:7e37af9d69ef

7011379: G1: overly long concurrent marking cycles Summary: This changeset introduces filtering of SATB buffers at the point when they are about to be enqueued. If this filtering clears enough entries on each buffer, the buffer can then be re-used and not enqueued. This cuts down the number of SATB buffers that need to be processed by the concurrent marking threads. Reviewed-by: johnc, ysr
author tonyp
date Wed, 19 Jan 2011 09:35:17 -0500
parents 2d160770d2e5
children 02f49b66361a
rev   line source
ysr@342 1 /*
johnc@1625 2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
ysr@342 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ysr@342 4 *
ysr@342 5 * This code is free software; you can redistribute it and/or modify it
ysr@342 6 * under the terms of the GNU General Public License version 2 only, as
ysr@342 7 * published by the Free Software Foundation.
ysr@342 8 *
ysr@342 9 * This code is distributed in the hope that it will be useful, but WITHOUT
ysr@342 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ysr@342 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ysr@342 12 * version 2 for more details (a copy is included in the LICENSE file that
ysr@342 13 * accompanied this code).
ysr@342 14 *
ysr@342 15 * You should have received a copy of the GNU General Public License version
ysr@342 16 * 2 along with this work; if not, write to the Free Software Foundation,
ysr@342 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ysr@342 18 *
trims@1472 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1472 20 * or visit www.oracle.com if you need additional information or have any
trims@1472 21 * questions.
ysr@342 22 *
ysr@342 23 */
ysr@342 24
stefank@1879 25 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTG1REFINE_HPP
stefank@1879 26 #define SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTG1REFINE_HPP
stefank@1879 27
stefank@1879 28 #include "memory/allocation.hpp"
stefank@1879 29 #include "memory/cardTableModRefBS.hpp"
stefank@1879 30 #include "runtime/thread.hpp"
stefank@1879 31 #include "utilities/globalDefinitions.hpp"
stefank@1879 32
ysr@342 33 // Forward decl
ysr@342 34 class ConcurrentG1RefineThread;
ysr@342 35 class G1RemSet;
ysr@342 36
apetrusenko@549 37 class ConcurrentG1Refine: public CHeapObj {
iveresov@794 38 ConcurrentG1RefineThread** _threads;
iveresov@794 39 int _n_threads;
iveresov@1111 40 int _n_worker_threads;
iveresov@1111 41 /*
iveresov@1111 42 * The value of the update buffer queue length falls into one of 3 zones:
iveresov@1111 43 * green, yellow, red. If the value is in [0, green) nothing is
iveresov@1111 44 * done, the buffers are left unprocessed to enable the caching effect of the
iveresov@1111 45 * dirtied cards. In the yellow zone [green, yellow) the concurrent refinement
iveresov@1111 46 * threads are gradually activated. In [yellow, red) all threads are
iveresov@1111 47 * running. If the length becomes red (max queue length) the mutators start
iveresov@1111 48 * processing the buffers.
iveresov@1111 49 *
tonyp@1282 50 * There are some interesting cases (when G1UseAdaptiveConcRefinement
tonyp@1282 51 * is turned off):
iveresov@1111 52 * 1) green = yellow = red = 0. In this case the mutator will process all
iveresov@1111 53 * buffers. Except for those that are created by the deferred updates
iveresov@1111 54 * machinery during a collection.
iveresov@1111 55 * 2) green = 0. Means no caching. Can be a good way to minimize the
iveresov@1111 56 * amount of time spent updating rsets during a collection.
iveresov@1111 57 */
iveresov@1111 58 int _green_zone;
iveresov@1111 59 int _yellow_zone;
iveresov@1111 60 int _red_zone;
iveresov@1111 61
iveresov@1111 62 int _thread_threshold_step;
iveresov@1111 63
iveresov@1111 64 // Reset the threshold step value based of the current zone boundaries.
iveresov@1111 65 void reset_threshold_step();
johnc@890 66
ysr@342 67 // The cache for card refinement.
johnc@890 68 bool _use_cache;
johnc@890 69 bool _def_use_cache;
ysr@342 70
johnc@890 71 size_t _n_periods; // Used as clearing epoch
johnc@890 72
johnc@890 73 // An evicting cache of the number of times each card
johnc@890 74 // is accessed. Reduces, but does not eliminate, the amount
johnc@890 75 // of duplicated processing of dirty cards.
johnc@890 76
johnc@890 77 enum SomePrivateConstants {
johnc@890 78 epoch_bits = 32,
johnc@890 79 card_num_shift = epoch_bits,
johnc@890 80 epoch_mask = AllBits,
johnc@890 81 card_num_mask = AllBits,
johnc@890 82
johnc@890 83 // The initial cache size is approximately this fraction
johnc@890 84 // of a maximal cache (i.e. the size needed for all cards
johnc@890 85 // in the heap)
johnc@890 86 InitialCacheFraction = 512
johnc@890 87 };
johnc@890 88
johnc@890 89 const static julong card_num_mask_in_place =
johnc@890 90 (julong) card_num_mask << card_num_shift;
johnc@890 91
johnc@890 92 typedef struct {
johnc@890 93 julong _value; // | card_num | epoch |
johnc@890 94 } CardEpochCacheEntry;
johnc@890 95
johnc@890 96 julong make_epoch_entry(unsigned int card_num, unsigned int epoch) {
johnc@890 97 assert(0 <= card_num && card_num < _max_n_card_counts, "Bounds");
johnc@890 98 assert(0 <= epoch && epoch <= _n_periods, "must be");
johnc@890 99
johnc@890 100 return ((julong) card_num << card_num_shift) | epoch;
johnc@890 101 }
johnc@890 102
johnc@890 103 unsigned int extract_epoch(julong v) {
johnc@890 104 return (v & epoch_mask);
johnc@890 105 }
johnc@890 106
johnc@890 107 unsigned int extract_card_num(julong v) {
johnc@890 108 return (v & card_num_mask_in_place) >> card_num_shift;
johnc@890 109 }
johnc@890 110
johnc@890 111 typedef struct {
johnc@890 112 unsigned char _count;
johnc@890 113 unsigned char _evict_count;
johnc@890 114 } CardCountCacheEntry;
johnc@890 115
johnc@890 116 CardCountCacheEntry* _card_counts;
johnc@890 117 CardEpochCacheEntry* _card_epochs;
johnc@890 118
johnc@890 119 // The current number of buckets in the card count cache
johnc@890 120 unsigned _n_card_counts;
johnc@890 121
johnc@890 122 // The max number of buckets required for the number of
johnc@890 123 // cards for the entire reserved heap
johnc@890 124 unsigned _max_n_card_counts;
johnc@890 125
johnc@890 126 // Possible sizes of the cache: odd primes that roughly double in size.
johnc@890 127 // (See jvmtiTagMap.cpp).
johnc@890 128 static int _cc_cache_sizes[];
johnc@890 129
johnc@890 130 // The index in _cc_cache_sizes corresponding to the size of
johnc@890 131 // _card_counts.
johnc@890 132 int _cache_size_index;
johnc@890 133
johnc@890 134 bool _expand_card_counts;
johnc@890 135
johnc@890 136 const jbyte* _ct_bot;
johnc@889 137
johnc@889 138 jbyte** _hot_cache;
johnc@889 139 int _hot_cache_size;
johnc@889 140 int _n_hot;
johnc@889 141 int _hot_cache_idx;
johnc@889 142
johnc@889 143 int _hot_cache_par_chunk_size;
johnc@889 144 volatile int _hot_cache_par_claimed_idx;
ysr@342 145
johnc@890 146 // Needed to workaround 6817995
johnc@890 147 CardTableModRefBS* _ct_bs;
johnc@890 148 G1CollectedHeap* _g1h;
johnc@890 149
johnc@890 150 // Expands the array that holds the card counts to the next size up
johnc@890 151 void expand_card_count_cache();
johnc@890 152
johnc@890 153 // hash a given key (index of card_ptr) with the specified size
johnc@890 154 static unsigned int hash(size_t key, int size) {
johnc@890 155 return (unsigned int) key % size;
johnc@890 156 }
johnc@890 157
johnc@890 158 // hash a given key (index of card_ptr)
johnc@890 159 unsigned int hash(size_t key) {
johnc@890 160 return hash(key, _n_card_counts);
johnc@890 161 }
johnc@890 162
johnc@890 163 unsigned ptr_2_card_num(jbyte* card_ptr) {
johnc@890 164 return (unsigned) (card_ptr - _ct_bot);
johnc@890 165 }
johnc@890 166
johnc@890 167 jbyte* card_num_2_ptr(unsigned card_num) {
johnc@890 168 return (jbyte*) (_ct_bot + card_num);
johnc@890 169 }
johnc@890 170
ysr@342 171 // Returns the count of this card after incrementing it.
johnc@890 172 jbyte* add_card_count(jbyte* card_ptr, int* count, bool* defer);
ysr@342 173
johnc@890 174 // Returns true if this card is in a young region
johnc@890 175 bool is_young_card(jbyte* card_ptr);
johnc@890 176
ysr@342 177 public:
ysr@342 178 ConcurrentG1Refine();
ysr@342 179 ~ConcurrentG1Refine();
ysr@342 180
ysr@342 181 void init(); // Accomplish some initialization that has to wait.
iveresov@794 182 void stop();
ysr@342 183
iveresov@1111 184 void reinitialize_threads();
iveresov@1111 185
iveresov@794 186 // Iterate over the conc refine threads
iveresov@794 187 void threads_do(ThreadClosure *tc);
ysr@342 188
ysr@342 189 // If this is the first entry for the slot, writes into the cache and
ysr@342 190 // returns NULL. If it causes an eviction, returns the evicted pointer.
ysr@342 191 // Otherwise, its a cache hit, and returns NULL.
johnc@890 192 jbyte* cache_insert(jbyte* card_ptr, bool* defer);
ysr@342 193
ysr@342 194 // Process the cached entries.
johnc@1625 195 void clean_up_cache(int worker_i, G1RemSet* g1rs, DirtyCardQueue* into_cset_dcq);
ysr@342 196
johnc@889 197 // Set up for parallel processing of the cards in the hot cache
johnc@889 198 void clear_hot_cache_claimed_index() {
johnc@889 199 _hot_cache_par_claimed_idx = 0;
johnc@889 200 }
johnc@889 201
ysr@342 202 // Discard entries in the hot cache.
ysr@342 203 void clear_hot_cache() {
ysr@342 204 _hot_cache_idx = 0; _n_hot = 0;
ysr@342 205 }
ysr@342 206
ysr@342 207 bool hot_cache_is_empty() { return _n_hot == 0; }
ysr@342 208
ysr@342 209 bool use_cache() { return _use_cache; }
ysr@342 210 void set_use_cache(bool b) {
ysr@342 211 if (b) _use_cache = _def_use_cache;
ysr@342 212 else _use_cache = false;
ysr@342 213 }
ysr@342 214
ysr@342 215 void clear_and_record_card_counts();
iveresov@795 216
iveresov@1111 217 static int thread_num();
tonyp@1019 218
tonyp@1019 219 void print_worker_threads_on(outputStream* st) const;
iveresov@1111 220
iveresov@1111 221 void set_green_zone(int x) { _green_zone = x; }
iveresov@1111 222 void set_yellow_zone(int x) { _yellow_zone = x; }
iveresov@1111 223 void set_red_zone(int x) { _red_zone = x; }
iveresov@1111 224
iveresov@1111 225 int green_zone() const { return _green_zone; }
iveresov@1111 226 int yellow_zone() const { return _yellow_zone; }
iveresov@1111 227 int red_zone() const { return _red_zone; }
iveresov@1111 228
iveresov@1111 229 int total_thread_num() const { return _n_threads; }
iveresov@1111 230 int worker_thread_num() const { return _n_worker_threads; }
iveresov@1111 231
iveresov@1111 232 int thread_threshold_step() const { return _thread_threshold_step; }
ysr@342 233 };
stefank@1879 234
stefank@1879 235 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTG1REFINE_HPP