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

Fri, 10 Oct 2014 15:51:58 +0200

author
tschatzl
date
Fri, 10 Oct 2014 15:51:58 +0200
changeset 7257
e7d0505c8a30
parent 6930
570cb6369f17
child 7535
7ae4e26cb1e0
child 8662
9975dd8382d5
permissions
-rw-r--r--

8059758: Footprint regressions with JDK-8038423
Summary: Changes in JDK-8038423 always initialize (zero out) virtual memory used for auxiliary data structures. This causes a footprint regression for G1 in startup benchmarks. This is because they do not touch that memory at all, so the operating system does not actually commit these pages. The fix is to, if the initialization value of the data structures matches the default value of just committed memory (=0), do not do anything.
Reviewed-by: jwilhelm, brutisso

ysr@777 1 /*
johnc@2060 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
stefank@2314 25 #include "precompiled.hpp"
stefank@2314 26 #include "gc_implementation/g1/dirtyCardQueue.hpp"
tschatzl@6541 27 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
stefank@2314 28 #include "gc_implementation/g1/heapRegionRemSet.hpp"
stefank@2314 29 #include "runtime/atomic.hpp"
stefank@2314 30 #include "runtime/mutexLocker.hpp"
stefank@2314 31 #include "runtime/safepoint.hpp"
stefank@4299 32 #include "runtime/thread.inline.hpp"
stefank@2314 33 #include "utilities/workgroup.hpp"
ysr@777 34
ysr@777 35 bool DirtyCardQueue::apply_closure(CardTableEntryClosure* cl,
ysr@777 36 bool consume,
vkempik@6552 37 uint worker_i) {
ysr@777 38 bool res = true;
ysr@777 39 if (_buf != NULL) {
ysr@777 40 res = apply_closure_to_buffer(cl, _buf, _index, _sz,
ysr@777 41 consume,
vkempik@6552 42 worker_i);
ysr@777 43 if (res && consume) _index = _sz;
ysr@777 44 }
ysr@777 45 return res;
ysr@777 46 }
ysr@777 47
ysr@777 48 bool DirtyCardQueue::apply_closure_to_buffer(CardTableEntryClosure* cl,
ysr@777 49 void** buf,
ysr@777 50 size_t index, size_t sz,
ysr@777 51 bool consume,
vkempik@6552 52 uint worker_i) {
ysr@777 53 if (cl == NULL) return true;
ysr@777 54 for (size_t i = index; i < sz; i += oopSize) {
ysr@777 55 int ind = byte_index_to_index((int)i);
ysr@777 56 jbyte* card_ptr = (jbyte*)buf[ind];
ysr@777 57 if (card_ptr != NULL) {
ysr@777 58 // Set the entry to null, so we don't do it again (via the test
ysr@777 59 // above) if we reconsider this buffer.
ysr@777 60 if (consume) buf[ind] = NULL;
ysr@777 61 if (!cl->do_card_ptr(card_ptr, worker_i)) return false;
ysr@777 62 }
ysr@777 63 }
ysr@777 64 return true;
ysr@777 65 }
ysr@777 66
ysr@777 67 #ifdef _MSC_VER // the use of 'this' below gets a warning, make it go away
ysr@777 68 #pragma warning( disable:4355 ) // 'this' : used in base member initializer list
ysr@777 69 #endif // _MSC_VER
ysr@777 70
iveresov@1546 71 DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) :
iveresov@1546 72 PtrQueueSet(notify_when_complete),
tschatzl@6930 73 _mut_process_closure(NULL),
ysr@777 74 _shared_dirty_card_queue(this, true /*perm*/),
ysr@777 75 _free_ids(NULL),
ysr@777 76 _processed_buffers_mut(0), _processed_buffers_rs_thread(0)
ysr@777 77 {
ysr@777 78 _all_active = true;
ysr@777 79 }
ysr@777 80
iveresov@1230 81 // Determines how many mutator threads can process the buffers in parallel.
vkempik@6552 82 uint DirtyCardQueueSet::num_par_ids() {
vkempik@6552 83 return (uint)os::processor_count();
ysr@777 84 }
ysr@777 85
tschatzl@6930 86 void DirtyCardQueueSet::initialize(CardTableEntryClosure* cl, Monitor* cbl_mon, Mutex* fl_lock,
iveresov@1546 87 int process_completed_threshold,
ysr@777 88 int max_completed_queue,
iveresov@1051 89 Mutex* lock, PtrQueueSet* fl_owner) {
tschatzl@6930 90 _mut_process_closure = cl;
iveresov@1546 91 PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold,
iveresov@1546 92 max_completed_queue, fl_owner);
tonyp@1318 93 set_buffer_size(G1UpdateBufferSize);
ysr@777 94 _shared_dirty_card_queue.set_lock(lock);
ysr@777 95 _free_ids = new FreeIdSet((int) num_par_ids(), _cbl_mon);
ysr@777 96 }
ysr@777 97
ysr@777 98 void DirtyCardQueueSet::handle_zero_index_for_thread(JavaThread* t) {
ysr@777 99 t->dirty_card_queue().handle_zero_index();
ysr@777 100 }
ysr@777 101
tschatzl@6930 102 void DirtyCardQueueSet::iterate_closure_all_threads(CardTableEntryClosure* cl,
tschatzl@6930 103 bool consume,
vkempik@6552 104 uint worker_i) {
ysr@777 105 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
ysr@777 106 for(JavaThread* t = Threads::first(); t; t = t->next()) {
tschatzl@6930 107 bool b = t->dirty_card_queue().apply_closure(cl, consume);
ysr@777 108 guarantee(b, "Should not be interrupted.");
ysr@777 109 }
tschatzl@6930 110 bool b = shared_dirty_card_queue()->apply_closure(cl,
ysr@777 111 consume,
ysr@777 112 worker_i);
ysr@777 113 guarantee(b, "Should not be interrupted.");
ysr@777 114 }
ysr@777 115
ysr@777 116 bool DirtyCardQueueSet::mut_process_buffer(void** buf) {
ysr@777 117
ysr@777 118 // Used to determine if we had already claimed a par_id
ysr@777 119 // before entering this method.
ysr@777 120 bool already_claimed = false;
ysr@777 121
ysr@777 122 // We grab the current JavaThread.
ysr@777 123 JavaThread* thread = JavaThread::current();
ysr@777 124
ysr@777 125 // We get the the number of any par_id that this thread
ysr@777 126 // might have already claimed.
vkempik@6552 127 uint worker_i = thread->get_claimed_par_id();
ysr@777 128
vkempik@6552 129 // If worker_i is not UINT_MAX then the thread has already claimed
ysr@777 130 // a par_id. We make note of it using the already_claimed value
vkempik@6552 131 if (worker_i != UINT_MAX) {
ysr@777 132 already_claimed = true;
ysr@777 133 } else {
ysr@777 134
ysr@777 135 // Otherwise we need to claim a par id
ysr@777 136 worker_i = _free_ids->claim_par_id();
ysr@777 137
ysr@777 138 // And store the par_id value in the thread
ysr@777 139 thread->set_claimed_par_id(worker_i);
ysr@777 140 }
ysr@777 141
ysr@777 142 bool b = false;
vkempik@6552 143 if (worker_i != UINT_MAX) {
tschatzl@6930 144 b = DirtyCardQueue::apply_closure_to_buffer(_mut_process_closure, buf, 0,
ysr@777 145 _sz, true, worker_i);
ysr@777 146 if (b) Atomic::inc(&_processed_buffers_mut);
ysr@777 147
ysr@777 148 // If we had not claimed an id before entering the method
ysr@777 149 // then we must release the id.
ysr@777 150 if (!already_claimed) {
ysr@777 151
ysr@777 152 // we release the id
ysr@777 153 _free_ids->release_par_id(worker_i);
ysr@777 154
vkempik@6552 155 // and set the claimed_id in the thread to UINT_MAX
vkempik@6552 156 thread->set_claimed_par_id(UINT_MAX);
ysr@777 157 }
ysr@777 158 }
ysr@777 159 return b;
ysr@777 160 }
ysr@777 161
iveresov@1546 162
iveresov@1546 163 BufferNode*
johnc@1525 164 DirtyCardQueueSet::get_completed_buffer(int stop_at) {
iveresov@1546 165 BufferNode* nd = NULL;
ysr@777 166 MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
ysr@777 167
ysr@777 168 if ((int)_n_completed_buffers <= stop_at) {
ysr@777 169 _process_completed = false;
ysr@777 170 return NULL;
ysr@777 171 }
ysr@777 172
ysr@777 173 if (_completed_buffers_head != NULL) {
ysr@777 174 nd = _completed_buffers_head;
iveresov@1546 175 _completed_buffers_head = nd->next();
ysr@777 176 if (_completed_buffers_head == NULL)
ysr@777 177 _completed_buffers_tail = NULL;
ysr@777 178 _n_completed_buffers--;
iveresov@1546 179 assert(_n_completed_buffers >= 0, "Invariant");
ysr@777 180 }
ysr@777 181 debug_only(assert_completed_buffer_list_len_correct_locked());
ysr@777 182 return nd;
ysr@777 183 }
ysr@777 184
ysr@777 185 bool DirtyCardQueueSet::
johnc@2060 186 apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl,
vkempik@6552 187 uint worker_i,
iveresov@1546 188 BufferNode* nd) {
ysr@777 189 if (nd != NULL) {
iveresov@1546 190 void **buf = BufferNode::make_buffer_from_node(nd);
iveresov@1546 191 size_t index = nd->index();
ysr@777 192 bool b =
johnc@2060 193 DirtyCardQueue::apply_closure_to_buffer(cl, buf,
iveresov@1546 194 index, _sz,
ysr@777 195 true, worker_i);
ysr@777 196 if (b) {
ysr@777 197 deallocate_buffer(buf);
ysr@777 198 return true; // In normal case, go on to next buffer.
ysr@777 199 } else {
iveresov@1546 200 enqueue_complete_buffer(buf, index);
ysr@777 201 return false;
ysr@777 202 }
ysr@777 203 } else {
ysr@777 204 return false;
ysr@777 205 }
ysr@777 206 }
ysr@777 207
johnc@2060 208 bool DirtyCardQueueSet::apply_closure_to_completed_buffer(CardTableEntryClosure* cl,
vkempik@6552 209 uint worker_i,
johnc@2060 210 int stop_at,
johnc@2060 211 bool during_pause) {
johnc@2060 212 assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause");
johnc@2060 213 BufferNode* nd = get_completed_buffer(stop_at);
johnc@2060 214 bool res = apply_closure_to_completed_buffer_helper(cl, worker_i, nd);
johnc@2060 215 if (res) Atomic::inc(&_processed_buffers_rs_thread);
johnc@2060 216 return res;
johnc@2060 217 }
johnc@2060 218
tschatzl@6930 219 void DirtyCardQueueSet::apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl) {
iveresov@1546 220 BufferNode* nd = _completed_buffers_head;
ysr@777 221 while (nd != NULL) {
ysr@777 222 bool b =
tschatzl@6930 223 DirtyCardQueue::apply_closure_to_buffer(cl,
iveresov@1546 224 BufferNode::make_buffer_from_node(nd),
iveresov@1546 225 0, _sz, false);
ysr@777 226 guarantee(b, "Should not stop early.");
iveresov@1546 227 nd = nd->next();
ysr@777 228 }
ysr@777 229 }
ysr@777 230
tschatzl@6930 231 void DirtyCardQueueSet::par_apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl) {
tschatzl@6930 232 BufferNode* nd = _cur_par_buffer_node;
tschatzl@6930 233 while (nd != NULL) {
tschatzl@6930 234 BufferNode* next = (BufferNode*)nd->next();
tschatzl@6930 235 BufferNode* actual = (BufferNode*)Atomic::cmpxchg_ptr((void*)next, (volatile void*)&_cur_par_buffer_node, (void*)nd);
tschatzl@6930 236 if (actual == nd) {
tschatzl@6930 237 bool b =
tschatzl@6930 238 DirtyCardQueue::apply_closure_to_buffer(cl,
tschatzl@6930 239 BufferNode::make_buffer_from_node(actual),
tschatzl@6930 240 0, _sz, false);
tschatzl@6930 241 guarantee(b, "Should not stop early.");
tschatzl@6930 242 nd = next;
tschatzl@6930 243 } else {
tschatzl@6930 244 nd = actual;
tschatzl@6930 245 }
tschatzl@6930 246 }
tschatzl@6930 247 }
tschatzl@6930 248
johnc@2060 249 // Deallocates any completed log buffers
johnc@2060 250 void DirtyCardQueueSet::clear() {
iveresov@1546 251 BufferNode* buffers_to_delete = NULL;
ysr@777 252 {
ysr@777 253 MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
ysr@777 254 while (_completed_buffers_head != NULL) {
iveresov@1546 255 BufferNode* nd = _completed_buffers_head;
iveresov@1546 256 _completed_buffers_head = nd->next();
iveresov@1546 257 nd->set_next(buffers_to_delete);
ysr@777 258 buffers_to_delete = nd;
ysr@777 259 }
ysr@777 260 _n_completed_buffers = 0;
ysr@777 261 _completed_buffers_tail = NULL;
ysr@777 262 debug_only(assert_completed_buffer_list_len_correct_locked());
ysr@777 263 }
ysr@777 264 while (buffers_to_delete != NULL) {
iveresov@1546 265 BufferNode* nd = buffers_to_delete;
iveresov@1546 266 buffers_to_delete = nd->next();
iveresov@1546 267 deallocate_buffer(BufferNode::make_buffer_from_node(nd));
ysr@777 268 }
johnc@2060 269
johnc@2060 270 }
johnc@2060 271
johnc@2060 272 void DirtyCardQueueSet::abandon_logs() {
johnc@2060 273 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
johnc@2060 274 clear();
ysr@777 275 // Since abandon is done only at safepoints, we can safely manipulate
ysr@777 276 // these queues.
ysr@777 277 for (JavaThread* t = Threads::first(); t; t = t->next()) {
ysr@777 278 t->dirty_card_queue().reset();
ysr@777 279 }
ysr@777 280 shared_dirty_card_queue()->reset();
ysr@777 281 }
ysr@777 282
ysr@777 283
ysr@777 284 void DirtyCardQueueSet::concatenate_logs() {
ysr@777 285 // Iterate over all the threads, if we find a partial log add it to
ysr@777 286 // the global list of logs. Temporarily turn off the limit on the number
ysr@777 287 // of outstanding buffers.
ysr@777 288 int save_max_completed_queue = _max_completed_queue;
ysr@777 289 _max_completed_queue = max_jint;
ysr@777 290 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
ysr@777 291 for (JavaThread* t = Threads::first(); t; t = t->next()) {
ysr@777 292 DirtyCardQueue& dcq = t->dirty_card_queue();
ysr@777 293 if (dcq.size() != 0) {
ysr@777 294 void **buf = t->dirty_card_queue().get_buf();
ysr@777 295 // We must NULL out the unused entries, then enqueue.
ysr@777 296 for (size_t i = 0; i < t->dirty_card_queue().get_index(); i += oopSize) {
ysr@777 297 buf[PtrQueue::byte_index_to_index((int)i)] = NULL;
ysr@777 298 }
ysr@777 299 enqueue_complete_buffer(dcq.get_buf(), dcq.get_index());
ysr@777 300 dcq.reinitialize();
ysr@777 301 }
ysr@777 302 }
ysr@777 303 if (_shared_dirty_card_queue.size() != 0) {
ysr@777 304 enqueue_complete_buffer(_shared_dirty_card_queue.get_buf(),
ysr@777 305 _shared_dirty_card_queue.get_index());
ysr@777 306 _shared_dirty_card_queue.reinitialize();
ysr@777 307 }
ysr@777 308 // Restore the completed buffer queue limit.
ysr@777 309 _max_completed_queue = save_max_completed_queue;
ysr@777 310 }

mercurial