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

Mon, 18 May 2009 11:52:46 -0700

author
iveresov
date
Mon, 18 May 2009 11:52:46 -0700
changeset 1230
215f81b4d9b3
parent 1229
315a5d70b295
child 1234
f89cf529c3c7
permissions
-rw-r--r--

6841831: G1: assert(contains_reference(from),"We just added it!") fires
Summary: During parallel rset updating we have to make sure that the worker ids of the refinement threads do not intersect with the worker ids that can be claimed by the mutator threads.
Reviewed-by: tonyp

ysr@777 1 /*
ysr@777 2 * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
ysr@777 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ysr@777 4 *
ysr@777 5 * This code is free software; you can redistribute it and/or modify it
ysr@777 6 * under the terms of the GNU General Public License version 2 only, as
ysr@777 7 * published by the Free Software Foundation.
ysr@777 8 *
ysr@777 9 * This code is distributed in the hope that it will be useful, but WITHOUT
ysr@777 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ysr@777 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ysr@777 12 * version 2 for more details (a copy is included in the LICENSE file that
ysr@777 13 * accompanied this code).
ysr@777 14 *
ysr@777 15 * You should have received a copy of the GNU General Public License version
ysr@777 16 * 2 along with this work; if not, write to the Free Software Foundation,
ysr@777 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ysr@777 18 *
ysr@777 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
ysr@777 20 * CA 95054 USA or visit www.sun.com if you need additional information or
ysr@777 21 * have any questions.
ysr@777 22 *
ysr@777 23 */
ysr@777 24
ysr@777 25 #include "incls/_precompiled.incl"
ysr@777 26 #include "incls/_concurrentG1Refine.cpp.incl"
ysr@777 27
ysr@777 28 ConcurrentG1Refine::ConcurrentG1Refine() :
ysr@777 29 _card_counts(NULL), _cur_card_count_histo(NULL), _cum_card_count_histo(NULL),
ysr@777 30 _hot_cache(NULL),
ysr@777 31 _def_use_cache(false), _use_cache(false),
iveresov@1229 32 _n_periods(0), _total_cards(0), _total_travs(0),
iveresov@1229 33 _threads(NULL), _n_threads(0)
ysr@777 34 {
ysr@777 35 if (G1ConcRefine) {
iveresov@1230 36 _n_threads = (int)thread_num();
iveresov@1229 37 if (_n_threads > 0) {
iveresov@1229 38 _threads = NEW_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _n_threads);
iveresov@1230 39 int worker_id_offset = (int)DirtyCardQueueSet::num_par_ids();
iveresov@1229 40 ConcurrentG1RefineThread *next = NULL;
iveresov@1229 41 for (int i = _n_threads - 1; i >= 0; i--) {
iveresov@1230 42 ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, worker_id_offset, i);
iveresov@1229 43 assert(t != NULL, "Conc refine should have been created");
iveresov@1229 44 assert(t->cg1r() == this, "Conc refine thread should refer to this");
iveresov@1229 45 _threads[i] = t;
iveresov@1229 46 next = t;
iveresov@1229 47 }
iveresov@1229 48 }
ysr@777 49 }
ysr@777 50 }
ysr@777 51
iveresov@1230 52 size_t ConcurrentG1Refine::thread_num() {
iveresov@1230 53 if (G1ConcRefine) {
iveresov@1230 54 return (G1ParallelRSetThreads > 0) ? G1ParallelRSetThreads : ParallelGCThreads;
iveresov@1230 55 }
iveresov@1230 56 return 0;
iveresov@1230 57 }
iveresov@1230 58
ysr@777 59 void ConcurrentG1Refine::init() {
ysr@777 60 if (G1ConcRSLogCacheSize > 0 || G1ConcRSCountTraversals) {
ysr@777 61 G1CollectedHeap* g1h = G1CollectedHeap::heap();
ysr@777 62 _n_card_counts =
ysr@777 63 (unsigned) (g1h->g1_reserved_obj_bytes() >> CardTableModRefBS::card_shift);
ysr@777 64 _card_counts = NEW_C_HEAP_ARRAY(unsigned char, _n_card_counts);
ysr@777 65 for (size_t i = 0; i < _n_card_counts; i++) _card_counts[i] = 0;
ysr@777 66 ModRefBarrierSet* bs = g1h->mr_bs();
ysr@777 67 guarantee(bs->is_a(BarrierSet::CardTableModRef), "Precondition");
ysr@777 68 CardTableModRefBS* ctbs = (CardTableModRefBS*)bs;
ysr@777 69 _ct_bot = ctbs->byte_for_const(g1h->reserved_region().start());
ysr@777 70 if (G1ConcRSCountTraversals) {
ysr@777 71 _cur_card_count_histo = NEW_C_HEAP_ARRAY(unsigned, 256);
ysr@777 72 _cum_card_count_histo = NEW_C_HEAP_ARRAY(unsigned, 256);
ysr@777 73 for (int i = 0; i < 256; i++) {
ysr@777 74 _cur_card_count_histo[i] = 0;
ysr@777 75 _cum_card_count_histo[i] = 0;
ysr@777 76 }
ysr@777 77 }
ysr@777 78 }
ysr@777 79 if (G1ConcRSLogCacheSize > 0) {
ysr@777 80 _def_use_cache = true;
ysr@777 81 _use_cache = true;
ysr@777 82 _hot_cache_size = (1 << G1ConcRSLogCacheSize);
ysr@777 83 _hot_cache = NEW_C_HEAP_ARRAY(jbyte*, _hot_cache_size);
ysr@777 84 _n_hot = 0;
ysr@777 85 _hot_cache_idx = 0;
ysr@777 86 }
ysr@777 87 }
ysr@777 88
iveresov@1229 89 void ConcurrentG1Refine::stop() {
iveresov@1229 90 if (_threads != NULL) {
iveresov@1229 91 for (int i = 0; i < _n_threads; i++) {
iveresov@1229 92 _threads[i]->stop();
iveresov@1229 93 }
iveresov@1229 94 }
iveresov@1229 95 }
iveresov@1229 96
ysr@777 97 ConcurrentG1Refine::~ConcurrentG1Refine() {
ysr@777 98 if (G1ConcRSLogCacheSize > 0 || G1ConcRSCountTraversals) {
ysr@777 99 assert(_card_counts != NULL, "Logic");
ysr@777 100 FREE_C_HEAP_ARRAY(unsigned char, _card_counts);
ysr@777 101 assert(_cur_card_count_histo != NULL, "Logic");
ysr@777 102 FREE_C_HEAP_ARRAY(unsigned, _cur_card_count_histo);
ysr@777 103 assert(_cum_card_count_histo != NULL, "Logic");
ysr@777 104 FREE_C_HEAP_ARRAY(unsigned, _cum_card_count_histo);
ysr@777 105 }
ysr@777 106 if (G1ConcRSLogCacheSize > 0) {
ysr@777 107 assert(_hot_cache != NULL, "Logic");
ysr@777 108 FREE_C_HEAP_ARRAY(jbyte*, _hot_cache);
ysr@777 109 }
iveresov@1229 110 if (_threads != NULL) {
iveresov@1229 111 for (int i = 0; i < _n_threads; i++) {
iveresov@1229 112 delete _threads[i];
iveresov@1229 113 }
iveresov@1229 114 FREE_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _n_threads);
ysr@777 115 }
ysr@777 116 }
ysr@777 117
iveresov@1229 118 void ConcurrentG1Refine::threads_do(ThreadClosure *tc) {
iveresov@1229 119 if (_threads != NULL) {
iveresov@1229 120 for (int i = 0; i < _n_threads; i++) {
iveresov@1229 121 tc->do_thread(_threads[i]);
iveresov@1229 122 }
ysr@777 123 }
ysr@777 124 }
ysr@777 125
ysr@777 126
ysr@777 127 int ConcurrentG1Refine::add_card_count(jbyte* card_ptr) {
ysr@777 128 size_t card_num = (card_ptr - _ct_bot);
ysr@777 129 guarantee(0 <= card_num && card_num < _n_card_counts, "Bounds");
ysr@777 130 unsigned char cnt = _card_counts[card_num];
ysr@777 131 if (cnt < 255) _card_counts[card_num]++;
ysr@777 132 return cnt;
ysr@777 133 _total_travs++;
ysr@777 134 }
ysr@777 135
ysr@777 136 jbyte* ConcurrentG1Refine::cache_insert(jbyte* card_ptr) {
ysr@777 137 int count = add_card_count(card_ptr);
ysr@777 138 // Count previously unvisited cards.
ysr@777 139 if (count == 0) _total_cards++;
ysr@777 140 // We'll assume a traversal unless we store it in the cache.
ysr@777 141 if (count < G1ConcRSHotCardLimit) {
ysr@777 142 _total_travs++;
ysr@777 143 return card_ptr;
ysr@777 144 }
ysr@777 145 // Otherwise, it's hot.
ysr@777 146 jbyte* res = NULL;
ysr@777 147 MutexLockerEx x(HotCardCache_lock, Mutex::_no_safepoint_check_flag);
ysr@777 148 if (_n_hot == _hot_cache_size) {
ysr@777 149 _total_travs++;
ysr@777 150 res = _hot_cache[_hot_cache_idx];
ysr@777 151 _n_hot--;
ysr@777 152 }
ysr@777 153 // Now _n_hot < _hot_cache_size, and we can insert at _hot_cache_idx.
ysr@777 154 _hot_cache[_hot_cache_idx] = card_ptr;
ysr@777 155 _hot_cache_idx++;
ysr@777 156 if (_hot_cache_idx == _hot_cache_size) _hot_cache_idx = 0;
ysr@777 157 _n_hot++;
ysr@777 158 return res;
ysr@777 159 }
ysr@777 160
ysr@777 161
ysr@777 162 void ConcurrentG1Refine::clean_up_cache(int worker_i, G1RemSet* g1rs) {
ysr@777 163 assert(!use_cache(), "cache should be disabled");
ysr@777 164 int start_ind = _hot_cache_idx-1;
ysr@777 165 for (int i = 0; i < _n_hot; i++) {
ysr@777 166 int ind = start_ind - i;
ysr@777 167 if (ind < 0) ind = ind + _hot_cache_size;
ysr@777 168 jbyte* entry = _hot_cache[ind];
ysr@777 169 if (entry != NULL) {
ysr@777 170 g1rs->concurrentRefineOneCard(entry, worker_i);
ysr@777 171 }
ysr@777 172 }
ysr@777 173 _n_hot = 0;
ysr@777 174 _hot_cache_idx = 0;
ysr@777 175 }
ysr@777 176
ysr@777 177 void ConcurrentG1Refine::clear_and_record_card_counts() {
ysr@777 178 if (G1ConcRSLogCacheSize == 0 && !G1ConcRSCountTraversals) return;
ysr@777 179 _n_periods++;
ysr@777 180 if (G1ConcRSCountTraversals) {
ysr@777 181 for (size_t i = 0; i < _n_card_counts; i++) {
ysr@777 182 unsigned char bucket = _card_counts[i];
ysr@777 183 _cur_card_count_histo[bucket]++;
ysr@777 184 _card_counts[i] = 0;
ysr@777 185 }
ysr@777 186 gclog_or_tty->print_cr("Card counts:");
ysr@777 187 for (int i = 0; i < 256; i++) {
ysr@777 188 if (_cur_card_count_histo[i] > 0) {
ysr@777 189 gclog_or_tty->print_cr(" %3d: %9d", i, _cur_card_count_histo[i]);
ysr@777 190 _cum_card_count_histo[i] += _cur_card_count_histo[i];
ysr@777 191 _cur_card_count_histo[i] = 0;
ysr@777 192 }
ysr@777 193 }
ysr@777 194 } else {
ysr@777 195 assert(G1ConcRSLogCacheSize > 0, "Logic");
ysr@777 196 Copy::fill_to_words((HeapWord*)(&_card_counts[0]),
ysr@777 197 _n_card_counts / HeapWordSize);
ysr@777 198 }
ysr@777 199 }
ysr@777 200
ysr@777 201 void
ysr@777 202 ConcurrentG1Refine::
ysr@777 203 print_card_count_histo_range(unsigned* histo, int from, int to,
ysr@777 204 float& cum_card_pct,
ysr@777 205 float& cum_travs_pct) {
ysr@777 206 unsigned cards = 0;
ysr@777 207 unsigned travs = 0;
ysr@777 208 guarantee(to <= 256, "Precondition");
ysr@777 209 for (int i = from; i < to-1; i++) {
ysr@777 210 cards += histo[i];
ysr@777 211 travs += histo[i] * i;
ysr@777 212 }
ysr@777 213 if (to == 256) {
ysr@777 214 unsigned histo_card_sum = 0;
ysr@777 215 unsigned histo_trav_sum = 0;
ysr@777 216 for (int i = 1; i < 255; i++) {
ysr@777 217 histo_trav_sum += histo[i] * i;
ysr@777 218 }
ysr@777 219 cards += histo[255];
ysr@777 220 // correct traversals for the last one.
ysr@777 221 unsigned travs_255 = (unsigned) (_total_travs - histo_trav_sum);
ysr@777 222 travs += travs_255;
ysr@777 223
ysr@777 224 } else {
ysr@777 225 cards += histo[to-1];
ysr@777 226 travs += histo[to-1] * (to-1);
ysr@777 227 }
ysr@777 228 float fperiods = (float)_n_periods;
ysr@777 229 float f_tot_cards = (float)_total_cards/fperiods;
ysr@777 230 float f_tot_travs = (float)_total_travs/fperiods;
ysr@777 231 if (cards > 0) {
ysr@777 232 float fcards = (float)cards/fperiods;
ysr@777 233 float ftravs = (float)travs/fperiods;
ysr@777 234 if (to == 256) {
ysr@777 235 gclog_or_tty->print(" %4d- %10.2f%10.2f", from, fcards, ftravs);
ysr@777 236 } else {
ysr@777 237 gclog_or_tty->print(" %4d-%4d %10.2f%10.2f", from, to-1, fcards, ftravs);
ysr@777 238 }
ysr@777 239 float pct_cards = fcards*100.0/f_tot_cards;
ysr@777 240 cum_card_pct += pct_cards;
ysr@777 241 float pct_travs = ftravs*100.0/f_tot_travs;
ysr@777 242 cum_travs_pct += pct_travs;
ysr@777 243 gclog_or_tty->print_cr("%10.2f%10.2f%10.2f%10.2f",
ysr@777 244 pct_cards, cum_card_pct,
ysr@777 245 pct_travs, cum_travs_pct);
ysr@777 246 }
ysr@777 247 }
ysr@777 248
ysr@777 249 void ConcurrentG1Refine::print_final_card_counts() {
ysr@777 250 if (!G1ConcRSCountTraversals) return;
ysr@777 251
ysr@777 252 gclog_or_tty->print_cr("Did %d total traversals of %d distinct cards.",
ysr@777 253 _total_travs, _total_cards);
ysr@777 254 float fperiods = (float)_n_periods;
ysr@777 255 gclog_or_tty->print_cr(" This is an average of %8.2f traversals, %8.2f cards, "
ysr@777 256 "per collection.", (float)_total_travs/fperiods,
ysr@777 257 (float)_total_cards/fperiods);
ysr@777 258 gclog_or_tty->print_cr(" This is an average of %8.2f traversals/distinct "
ysr@777 259 "dirty card.\n",
ysr@777 260 _total_cards > 0 ?
ysr@777 261 (float)_total_travs/(float)_total_cards : 0.0);
ysr@777 262
ysr@777 263
ysr@777 264 gclog_or_tty->print_cr("Histogram:\n\n%10s %10s%10s%10s%10s%10s%10s",
ysr@777 265 "range", "# cards", "# travs", "% cards", "(cum)",
ysr@777 266 "% travs", "(cum)");
ysr@777 267 gclog_or_tty->print_cr("------------------------------------------------------------"
ysr@777 268 "-------------");
ysr@777 269 float cum_cards_pct = 0.0;
ysr@777 270 float cum_travs_pct = 0.0;
ysr@777 271 for (int i = 1; i < 10; i++) {
ysr@777 272 print_card_count_histo_range(_cum_card_count_histo, i, i+1,
ysr@777 273 cum_cards_pct, cum_travs_pct);
ysr@777 274 }
ysr@777 275 for (int i = 10; i < 100; i += 10) {
ysr@777 276 print_card_count_histo_range(_cum_card_count_histo, i, i+10,
ysr@777 277 cum_cards_pct, cum_travs_pct);
ysr@777 278 }
ysr@777 279 print_card_count_histo_range(_cum_card_count_histo, 100, 150,
ysr@777 280 cum_cards_pct, cum_travs_pct);
ysr@777 281 print_card_count_histo_range(_cum_card_count_histo, 150, 200,
ysr@777 282 cum_cards_pct, cum_travs_pct);
ysr@777 283 print_card_count_histo_range(_cum_card_count_histo, 150, 255,
ysr@777 284 cum_cards_pct, cum_travs_pct);
ysr@777 285 print_card_count_histo_range(_cum_card_count_histo, 255, 256,
ysr@777 286 cum_cards_pct, cum_travs_pct);
ysr@777 287 }

mercurial