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

Mon, 02 Aug 2010 12:51:43 -0700

author
johnc
date
Mon, 02 Aug 2010 12:51:43 -0700
changeset 2060
2d160770d2e5
parent 1907
c18cbe5936b8
child 2314
f95d63e2154a
permissions
-rw-r--r--

6814437: G1: remove the _new_refs array
Summary: The per-worker _new_refs array is used to hold references that point into the collection set. It is populated during RSet updating and subsequently processed. In the event of an evacuation failure it processed again to recreate the RSets of regions in the collection set. Remove the per-worker _new_refs array by processing the references directly. Use a DirtyCardQueue to hold the cards containing the references so that the RSets of regions in the collection set can be recreated when handling an evacuation failure.
Reviewed-by: iveresov, jmasa, tonyp

ysr@777 1 /*
trims@1907 2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. 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 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
ysr@777 22 *
ysr@777 23 */
ysr@777 24
ysr@777 25 #include "incls/_precompiled.incl"
ysr@777 26 #include "incls/_concurrentG1RefineThread.cpp.incl"
ysr@777 27
ysr@777 28 ConcurrentG1RefineThread::
iveresov@1230 29 ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next,
iveresov@1230 30 int worker_id_offset, int worker_id) :
ysr@777 31 ConcurrentGCThread(),
iveresov@1230 32 _worker_id_offset(worker_id_offset),
iveresov@1229 33 _worker_id(worker_id),
iveresov@1229 34 _active(false),
iveresov@1229 35 _next(next),
iveresov@1546 36 _monitor(NULL),
ysr@777 37 _cg1r(cg1r),
iveresov@1546 38 _vtime_accum(0.0)
ysr@777 39 {
iveresov@1546 40
iveresov@1546 41 // Each thread has its own monitor. The i-th thread is responsible for signalling
iveresov@1546 42 // to thread i+1 if the number of buffers in the queue exceeds a threashold for this
iveresov@1546 43 // thread. Monitors are also used to wake up the threads during termination.
iveresov@1546 44 // The 0th worker in notified by mutator threads and has a special monitor.
iveresov@1546 45 // The last worker is used for young gen rset size sampling.
iveresov@1546 46 if (worker_id > 0) {
iveresov@1546 47 _monitor = new Monitor(Mutex::nonleaf, "Refinement monitor", true);
iveresov@1546 48 } else {
iveresov@1546 49 _monitor = DirtyCardQ_CBL_mon;
iveresov@1546 50 }
iveresov@1546 51 initialize();
ysr@777 52 create_and_start();
ysr@777 53 }
ysr@777 54
iveresov@1546 55 void ConcurrentG1RefineThread::initialize() {
iveresov@1546 56 if (_worker_id < cg1r()->worker_thread_num()) {
iveresov@1546 57 // Current thread activation threshold
iveresov@1546 58 _threshold = MIN2<int>(cg1r()->thread_threshold_step() * (_worker_id + 1) + cg1r()->green_zone(),
iveresov@1546 59 cg1r()->yellow_zone());
iveresov@1546 60 // A thread deactivates once the number of buffer reached a deactivation threshold
iveresov@1546 61 _deactivation_threshold = MAX2<int>(_threshold - cg1r()->thread_threshold_step(), cg1r()->green_zone());
iveresov@1546 62 } else {
iveresov@1546 63 set_active(true);
iveresov@1546 64 }
iveresov@1546 65 }
iveresov@1546 66
ysr@777 67 void ConcurrentG1RefineThread::sample_young_list_rs_lengths() {
ysr@777 68 G1CollectedHeap* g1h = G1CollectedHeap::heap();
ysr@777 69 G1CollectorPolicy* g1p = g1h->g1_policy();
ysr@777 70 if (g1p->adaptive_young_list_length()) {
ysr@777 71 int regions_visited = 0;
johnc@1829 72 g1h->young_list()->rs_length_sampling_init();
johnc@1829 73 while (g1h->young_list()->rs_length_sampling_more()) {
johnc@1829 74 g1h->young_list()->rs_length_sampling_next();
ysr@777 75 ++regions_visited;
ysr@777 76
ysr@777 77 // we try to yield every time we visit 10 regions
ysr@777 78 if (regions_visited == 10) {
ysr@777 79 if (_sts.should_yield()) {
ysr@777 80 _sts.yield("G1 refine");
ysr@777 81 // we just abandon the iteration
ysr@777 82 break;
ysr@777 83 }
ysr@777 84 regions_visited = 0;
ysr@777 85 }
ysr@777 86 }
ysr@777 87
ysr@777 88 g1p->check_prediction_validity();
ysr@777 89 }
ysr@777 90 }
ysr@777 91
iveresov@1546 92 void ConcurrentG1RefineThread::run_young_rs_sampling() {
iveresov@1546 93 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
iveresov@1546 94 _vtime_start = os::elapsedVTime();
iveresov@1546 95 while(!_should_terminate) {
iveresov@1546 96 _sts.join();
iveresov@1546 97 sample_young_list_rs_lengths();
iveresov@1546 98 _sts.leave();
iveresov@1546 99
iveresov@1546 100 if (os::supports_vtime()) {
iveresov@1546 101 _vtime_accum = (os::elapsedVTime() - _vtime_start);
iveresov@1546 102 } else {
iveresov@1546 103 _vtime_accum = 0.0;
iveresov@1546 104 }
iveresov@1546 105
iveresov@1546 106 MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
iveresov@1546 107 if (_should_terminate) {
iveresov@1546 108 break;
iveresov@1546 109 }
tonyp@1717 110 _monitor->wait(Mutex::_no_safepoint_check_flag, G1ConcRefinementServiceIntervalMillis);
iveresov@1546 111 }
iveresov@1546 112 }
iveresov@1546 113
iveresov@1546 114 void ConcurrentG1RefineThread::wait_for_completed_buffers() {
iveresov@1546 115 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
iveresov@1546 116 MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
iveresov@1546 117 while (!_should_terminate && !is_active()) {
iveresov@1546 118 _monitor->wait(Mutex::_no_safepoint_check_flag);
iveresov@1546 119 }
iveresov@1546 120 }
iveresov@1546 121
iveresov@1546 122 bool ConcurrentG1RefineThread::is_active() {
iveresov@1546 123 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
iveresov@1546 124 return _worker_id > 0 ? _active : dcqs.process_completed_buffers();
iveresov@1546 125 }
iveresov@1546 126
iveresov@1546 127 void ConcurrentG1RefineThread::activate() {
iveresov@1546 128 MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
iveresov@1546 129 if (_worker_id > 0) {
tonyp@1717 130 if (G1TraceConcRefinement) {
iveresov@1546 131 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
iveresov@1546 132 gclog_or_tty->print_cr("G1-Refine-activated worker %d, on threshold %d, current %d",
iveresov@1546 133 _worker_id, _threshold, (int)dcqs.completed_buffers_num());
iveresov@1546 134 }
iveresov@1546 135 set_active(true);
iveresov@1546 136 } else {
iveresov@1546 137 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
iveresov@1546 138 dcqs.set_process_completed(true);
iveresov@1546 139 }
iveresov@1546 140 _monitor->notify();
iveresov@1546 141 }
iveresov@1546 142
iveresov@1546 143 void ConcurrentG1RefineThread::deactivate() {
iveresov@1546 144 MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
iveresov@1546 145 if (_worker_id > 0) {
tonyp@1717 146 if (G1TraceConcRefinement) {
iveresov@1546 147 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
iveresov@1546 148 gclog_or_tty->print_cr("G1-Refine-deactivated worker %d, off threshold %d, current %d",
iveresov@1546 149 _worker_id, _deactivation_threshold, (int)dcqs.completed_buffers_num());
iveresov@1546 150 }
iveresov@1546 151 set_active(false);
iveresov@1546 152 } else {
iveresov@1546 153 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
iveresov@1546 154 dcqs.set_process_completed(false);
iveresov@1546 155 }
iveresov@1546 156 }
iveresov@1546 157
ysr@777 158 void ConcurrentG1RefineThread::run() {
ysr@777 159 initialize_in_thread();
ysr@777 160 wait_for_universe_init();
ysr@777 161
iveresov@1546 162 if (_worker_id >= cg1r()->worker_thread_num()) {
iveresov@1546 163 run_young_rs_sampling();
iveresov@1546 164 terminate();
johnc@1829 165 return;
iveresov@1546 166 }
iveresov@1546 167
iveresov@1546 168 _vtime_start = os::elapsedVTime();
ysr@777 169 while (!_should_terminate) {
iveresov@1229 170 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
iveresov@1546 171
iveresov@1546 172 // Wait for work
iveresov@1546 173 wait_for_completed_buffers();
iveresov@1546 174
iveresov@1546 175 if (_should_terminate) {
iveresov@1546 176 break;
iveresov@1229 177 }
iveresov@1229 178
iveresov@1546 179 _sts.join();
iveresov@1229 180
iveresov@1546 181 do {
iveresov@1546 182 int curr_buffer_num = (int)dcqs.completed_buffers_num();
iveresov@1546 183 // If the number of the buffers falls down into the yellow zone,
iveresov@1546 184 // that means that the transition period after the evacuation pause has ended.
iveresov@1546 185 if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cg1r()->yellow_zone()) {
iveresov@1546 186 dcqs.set_completed_queue_padding(0);
iveresov@1546 187 }
iveresov@1229 188
iveresov@1546 189 if (_worker_id > 0 && curr_buffer_num <= _deactivation_threshold) {
iveresov@1229 190 // If the number of the buffer has fallen below our threshold
iveresov@1229 191 // we should deactivate. The predecessor will reactivate this
iveresov@1229 192 // thread should the number of the buffers cross the threshold again.
iveresov@1229 193 deactivate();
iveresov@1229 194 break;
iveresov@1229 195 }
iveresov@1229 196
iveresov@1229 197 // Check if we need to activate the next thread.
iveresov@1546 198 if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) {
iveresov@1229 199 _next->activate();
iveresov@1229 200 }
iveresov@1546 201 } while (dcqs.apply_closure_to_completed_buffer(_worker_id + _worker_id_offset, cg1r()->green_zone()));
iveresov@1229 202
iveresov@1546 203 // We can exit the loop above while being active if there was a yield request.
iveresov@1546 204 if (is_active()) {
iveresov@1546 205 deactivate();
iveresov@1229 206 }
iveresov@1546 207
ysr@777 208 _sts.leave();
iveresov@1229 209
ysr@777 210 if (os::supports_vtime()) {
ysr@777 211 _vtime_accum = (os::elapsedVTime() - _vtime_start);
ysr@777 212 } else {
ysr@777 213 _vtime_accum = 0.0;
ysr@777 214 }
ysr@777 215 }
ysr@777 216 assert(_should_terminate, "just checking");
ysr@777 217 terminate();
ysr@777 218 }
ysr@777 219
ysr@777 220
ysr@777 221 void ConcurrentG1RefineThread::yield() {
tonyp@1717 222 if (G1TraceConcRefinement) {
tonyp@1717 223 gclog_or_tty->print_cr("G1-Refine-yield");
tonyp@1717 224 }
ysr@777 225 _sts.yield("G1 refine");
tonyp@1717 226 if (G1TraceConcRefinement) {
tonyp@1717 227 gclog_or_tty->print_cr("G1-Refine-yield-end");
tonyp@1717 228 }
ysr@777 229 }
ysr@777 230
ysr@777 231 void ConcurrentG1RefineThread::stop() {
ysr@777 232 // it is ok to take late safepoints here, if needed
ysr@777 233 {
ysr@777 234 MutexLockerEx mu(Terminator_lock);
ysr@777 235 _should_terminate = true;
ysr@777 236 }
ysr@777 237
ysr@777 238 {
iveresov@1546 239 MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
iveresov@1546 240 _monitor->notify();
ysr@777 241 }
ysr@777 242
ysr@777 243 {
ysr@777 244 MutexLockerEx mu(Terminator_lock);
ysr@777 245 while (!_has_terminated) {
ysr@777 246 Terminator_lock->wait();
ysr@777 247 }
ysr@777 248 }
tonyp@1717 249 if (G1TraceConcRefinement) {
tonyp@1717 250 gclog_or_tty->print_cr("G1-Refine-stop");
tonyp@1717 251 }
ysr@777 252 }
ysr@777 253
tonyp@1454 254 void ConcurrentG1RefineThread::print() const {
tonyp@1454 255 print_on(tty);
ysr@777 256 }
tonyp@1454 257
tonyp@1454 258 void ConcurrentG1RefineThread::print_on(outputStream* st) const {
tonyp@1454 259 st->print("\"G1 Concurrent Refinement Thread#%d\" ", _worker_id);
tonyp@1454 260 Thread::print_on(st);
tonyp@1454 261 st->cr();
tonyp@1454 262 }

mercurial