src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp

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

author
tschatzl
date
Fri, 10 Oct 2014 15:51:58 +0200
changeset 7257
e7d0505c8a30
parent 7094
9337d0e7ea4f
child 7535
7ae4e26cb1e0
child 7829
24c446b2460d
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

tonyp@2968 1 /*
drchase@6680 2 * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
tonyp@2968 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
tonyp@2968 4 *
tonyp@2968 5 * This code is free software; you can redistribute it and/or modify it
tonyp@2968 6 * under the terms of the GNU General Public License version 2 only, as
tonyp@2968 7 * published by the Free Software Foundation.
tonyp@2968 8 *
tonyp@2968 9 * This code is distributed in the hope that it will be useful, but WITHOUT
tonyp@2968 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
tonyp@2968 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
tonyp@2968 12 * version 2 for more details (a copy is included in the LICENSE file that
tonyp@2968 13 * accompanied this code).
tonyp@2968 14 *
tonyp@2968 15 * You should have received a copy of the GNU General Public License version
tonyp@2968 16 * 2 along with this work; if not, write to the Free Software Foundation,
tonyp@2968 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
tonyp@2968 18 *
tonyp@2968 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
tonyp@2968 20 * or visit www.oracle.com if you need additional information or have any
tonyp@2968 21 * questions.
tonyp@2968 22 *
tonyp@2968 23 */
tonyp@2968 24
tonyp@2968 25 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTMARK_INLINE_HPP
tonyp@2968 26 #define SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTMARK_INLINE_HPP
tonyp@2968 27
tonyp@2968 28 #include "gc_implementation/g1/concurrentMark.hpp"
tonyp@2968 29 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
tonyp@2968 30
johnc@4123 31 // Utility routine to set an exclusive range of cards on the given
johnc@4123 32 // card liveness bitmap
johnc@4123 33 inline void ConcurrentMark::set_card_bitmap_range(BitMap* card_bm,
johnc@4123 34 BitMap::idx_t start_idx,
johnc@4123 35 BitMap::idx_t end_idx,
johnc@4123 36 bool is_par) {
johnc@4123 37
johnc@4123 38 // Set the exclusive bit range [start_idx, end_idx).
johnc@4123 39 assert((end_idx - start_idx) > 0, "at least one card");
johnc@4123 40 assert(end_idx <= card_bm->size(), "sanity");
johnc@4123 41
johnc@4123 42 // Silently clip the end index
johnc@4123 43 end_idx = MIN2(end_idx, card_bm->size());
johnc@4123 44
johnc@4123 45 // For small ranges use a simple loop; otherwise use set_range or
johnc@4123 46 // use par_at_put_range (if parallel). The range is made up of the
johnc@4123 47 // cards that are spanned by an object/mem region so 8 cards will
johnc@4123 48 // allow up to object sizes up to 4K to be handled using the loop.
johnc@4123 49 if ((end_idx - start_idx) <= 8) {
johnc@4123 50 for (BitMap::idx_t i = start_idx; i < end_idx; i += 1) {
johnc@4123 51 if (is_par) {
johnc@4123 52 card_bm->par_set_bit(i);
johnc@4123 53 } else {
johnc@4123 54 card_bm->set_bit(i);
johnc@4123 55 }
johnc@4123 56 }
johnc@4123 57 } else {
johnc@4123 58 // Note BitMap::par_at_put_range() and BitMap::set_range() are exclusive.
johnc@4123 59 if (is_par) {
johnc@4123 60 card_bm->par_at_put_range(start_idx, end_idx, true);
johnc@4123 61 } else {
johnc@4123 62 card_bm->set_range(start_idx, end_idx);
johnc@4123 63 }
johnc@4123 64 }
johnc@4123 65 }
johnc@4123 66
johnc@3463 67 // Returns the index in the liveness accounting card bitmap
johnc@3463 68 // for the given address
johnc@3463 69 inline BitMap::idx_t ConcurrentMark::card_bitmap_index_for(HeapWord* addr) {
johnc@3463 70 // Below, the term "card num" means the result of shifting an address
johnc@3463 71 // by the card shift -- address 0 corresponds to card number 0. One
johnc@3463 72 // must subtract the card num of the bottom of the heap to obtain a
johnc@3463 73 // card table index.
johnc@3463 74 intptr_t card_num = intptr_t(uintptr_t(addr) >> CardTableModRefBS::card_shift);
johnc@3463 75 return card_num - heap_bottom_card_num();
johnc@3463 76 }
johnc@3463 77
johnc@3463 78 // Counts the given memory region in the given task/worker
johnc@3463 79 // counting data structures.
johnc@3463 80 inline void ConcurrentMark::count_region(MemRegion mr, HeapRegion* hr,
johnc@3463 81 size_t* marked_bytes_array,
johnc@3463 82 BitMap* task_card_bm) {
johnc@3463 83 G1CollectedHeap* g1h = _g1h;
mgerdin@5811 84 CardTableModRefBS* ct_bs = g1h->g1_barrier_set();
johnc@4123 85
johnc@3463 86 HeapWord* start = mr.start();
johnc@4123 87 HeapWord* end = mr.end();
johnc@3463 88 size_t region_size_bytes = mr.byte_size();
tschatzl@7091 89 uint index = hr->hrm_index();
johnc@3463 90
johnc@3463 91 assert(!hr->continuesHumongous(), "should not be HC region");
johnc@3463 92 assert(hr == g1h->heap_region_containing(start), "sanity");
johnc@3463 93 assert(hr == g1h->heap_region_containing(mr.last()), "sanity");
johnc@3463 94 assert(marked_bytes_array != NULL, "pre-condition");
johnc@3463 95 assert(task_card_bm != NULL, "pre-condition");
johnc@3463 96
johnc@3463 97 // Add to the task local marked bytes for this region.
johnc@3463 98 marked_bytes_array[index] += region_size_bytes;
johnc@3463 99
johnc@3463 100 BitMap::idx_t start_idx = card_bitmap_index_for(start);
johnc@4123 101 BitMap::idx_t end_idx = card_bitmap_index_for(end);
johnc@3463 102
johnc@4123 103 // Note: if we're looking at the last region in heap - end
johnc@4123 104 // could be actually just beyond the end of the heap; end_idx
johnc@4123 105 // will then correspond to a (non-existent) card that is also
johnc@4123 106 // just beyond the heap.
johnc@4123 107 if (g1h->is_in_g1_reserved(end) && !ct_bs->is_card_aligned(end)) {
johnc@4123 108 // end of region is not card aligned - incremement to cover
johnc@4123 109 // all the cards spanned by the region.
johnc@4123 110 end_idx += 1;
johnc@3463 111 }
johnc@4123 112 // The card bitmap is task/worker specific => no need to use
johnc@4123 113 // the 'par' BitMap routines.
johnc@4123 114 // Set bits in the exclusive bit range [start_idx, end_idx).
johnc@4123 115 set_card_bitmap_range(task_card_bm, start_idx, end_idx, false /* is_par */);
johnc@3463 116 }
johnc@3463 117
tonyp@3464 118 // Counts the given memory region in the task/worker counting
tonyp@3464 119 // data structures for the given worker id.
tonyp@3464 120 inline void ConcurrentMark::count_region(MemRegion mr,
tonyp@3464 121 HeapRegion* hr,
tonyp@3464 122 uint worker_id) {
tonyp@3464 123 size_t* marked_bytes_array = count_marked_bytes_array_for(worker_id);
tonyp@3464 124 BitMap* task_card_bm = count_card_bitmap_for(worker_id);
tonyp@3464 125 count_region(mr, hr, marked_bytes_array, task_card_bm);
tonyp@3464 126 }
tonyp@3464 127
johnc@3463 128 // Counts the given object in the given task/worker counting data structures.
johnc@3463 129 inline void ConcurrentMark::count_object(oop obj,
johnc@3463 130 HeapRegion* hr,
johnc@3463 131 size_t* marked_bytes_array,
johnc@3463 132 BitMap* task_card_bm) {
johnc@3463 133 MemRegion mr((HeapWord*)obj, obj->size());
johnc@3463 134 count_region(mr, hr, marked_bytes_array, task_card_bm);
johnc@3463 135 }
johnc@3463 136
johnc@3463 137 // Attempts to mark the given object and, if successful, counts
johnc@3463 138 // the object in the given task/worker counting structures.
johnc@3463 139 inline bool ConcurrentMark::par_mark_and_count(oop obj,
johnc@3463 140 HeapRegion* hr,
johnc@3463 141 size_t* marked_bytes_array,
johnc@3463 142 BitMap* task_card_bm) {
johnc@3463 143 HeapWord* addr = (HeapWord*)obj;
johnc@3463 144 if (_nextMarkBitMap->parMark(addr)) {
johnc@3463 145 // Update the task specific count data for the object.
johnc@3463 146 count_object(obj, hr, marked_bytes_array, task_card_bm);
johnc@3463 147 return true;
johnc@3463 148 }
johnc@3463 149 return false;
johnc@3463 150 }
johnc@3463 151
johnc@3463 152 // Attempts to mark the given object and, if successful, counts
johnc@3463 153 // the object in the task/worker counting structures for the
johnc@3463 154 // given worker id.
johnc@3463 155 inline bool ConcurrentMark::par_mark_and_count(oop obj,
tonyp@3464 156 size_t word_size,
tonyp@3464 157 HeapRegion* hr,
tonyp@3464 158 uint worker_id) {
tonyp@3464 159 HeapWord* addr = (HeapWord*)obj;
tonyp@3464 160 if (_nextMarkBitMap->parMark(addr)) {
tonyp@3464 161 MemRegion mr(addr, word_size);
tonyp@3464 162 count_region(mr, hr, worker_id);
tonyp@3464 163 return true;
tonyp@3464 164 }
tonyp@3464 165 return false;
tonyp@3464 166 }
tonyp@3464 167
johnc@3454 168 inline bool CMBitMapRO::iterate(BitMapClosure* cl, MemRegion mr) {
johnc@3454 169 HeapWord* start_addr = MAX2(startWord(), mr.start());
johnc@3454 170 HeapWord* end_addr = MIN2(endWord(), mr.end());
johnc@3454 171
johnc@3454 172 if (end_addr > start_addr) {
johnc@3454 173 // Right-open interval [start-offset, end-offset).
johnc@3454 174 BitMap::idx_t start_offset = heapWordToOffset(start_addr);
johnc@3454 175 BitMap::idx_t end_offset = heapWordToOffset(end_addr);
johnc@3454 176
johnc@3454 177 start_offset = _bm.get_next_one_offset(start_offset, end_offset);
johnc@3454 178 while (start_offset < end_offset) {
johnc@3454 179 if (!cl->do_bit(start_offset)) {
johnc@3454 180 return false;
johnc@3454 181 }
tamao@4733 182 HeapWord* next_addr = MIN2(nextObject(offsetToHeapWord(start_offset)), end_addr);
johnc@3454 183 BitMap::idx_t next_offset = heapWordToOffset(next_addr);
johnc@3454 184 start_offset = _bm.get_next_one_offset(next_offset, end_offset);
johnc@3454 185 }
johnc@3454 186 }
johnc@3454 187 return true;
johnc@3454 188 }
johnc@3454 189
johnc@3454 190 inline bool CMBitMapRO::iterate(BitMapClosure* cl) {
johnc@3454 191 MemRegion mr(startWord(), sizeInWords());
johnc@3454 192 return iterate(cl, mr);
johnc@3454 193 }
johnc@3454 194
tschatzl@7051 195 #define check_mark(addr) \
tschatzl@7051 196 assert(_bmStartWord <= (addr) && (addr) < (_bmStartWord + _bmWordSize), \
tschatzl@7051 197 "outside underlying space?"); \
tschatzl@7051 198 assert(G1CollectedHeap::heap()->is_in_exact(addr), \
tschatzl@7051 199 err_msg("Trying to access not available bitmap "PTR_FORMAT \
tschatzl@7051 200 " corresponding to "PTR_FORMAT" (%u)", \
tschatzl@7051 201 p2i(this), p2i(addr), G1CollectedHeap::heap()->addr_to_region(addr)));
tschatzl@7051 202
tschatzl@7051 203 inline void CMBitMap::mark(HeapWord* addr) {
tschatzl@7051 204 check_mark(addr);
tschatzl@7051 205 _bm.set_bit(heapWordToOffset(addr));
tschatzl@7051 206 }
tschatzl@7051 207
tschatzl@7051 208 inline void CMBitMap::clear(HeapWord* addr) {
tschatzl@7051 209 check_mark(addr);
tschatzl@7051 210 _bm.clear_bit(heapWordToOffset(addr));
tschatzl@7051 211 }
tschatzl@7051 212
tschatzl@7051 213 inline bool CMBitMap::parMark(HeapWord* addr) {
tschatzl@7051 214 check_mark(addr);
tschatzl@7051 215 return _bm.par_set_bit(heapWordToOffset(addr));
tschatzl@7051 216 }
tschatzl@7051 217
tschatzl@7051 218 inline bool CMBitMap::parClear(HeapWord* addr) {
tschatzl@7051 219 check_mark(addr);
tschatzl@7051 220 return _bm.par_clear_bit(heapWordToOffset(addr));
tschatzl@7051 221 }
tschatzl@7051 222
tschatzl@7051 223 #undef check_mark
tschatzl@7051 224
tonyp@2968 225 inline void CMTask::push(oop obj) {
tonyp@2968 226 HeapWord* objAddr = (HeapWord*) obj;
tonyp@2968 227 assert(_g1h->is_in_g1_reserved(objAddr), "invariant");
tonyp@2968 228 assert(!_g1h->is_on_master_free_list(
tonyp@2968 229 _g1h->heap_region_containing((HeapWord*) objAddr)), "invariant");
tonyp@2968 230 assert(!_g1h->is_obj_ill(obj), "invariant");
tonyp@2968 231 assert(_nextMarkBitMap->isMarked(objAddr), "invariant");
tonyp@2968 232
tonyp@2968 233 if (_cm->verbose_high()) {
drchase@6680 234 gclog_or_tty->print_cr("[%u] pushing " PTR_FORMAT, _worker_id, p2i((void*) obj));
tonyp@2968 235 }
tonyp@2968 236
tonyp@2968 237 if (!_task_queue->push(obj)) {
tonyp@2968 238 // The local task queue looks full. We need to push some entries
tonyp@2968 239 // to the global stack.
tonyp@2968 240
tonyp@2968 241 if (_cm->verbose_medium()) {
johnc@4173 242 gclog_or_tty->print_cr("[%u] task queue overflow, "
tonyp@2968 243 "moving entries to the global stack",
johnc@4173 244 _worker_id);
tonyp@2968 245 }
tonyp@2968 246 move_entries_to_global_stack();
tonyp@2968 247
tonyp@2968 248 // this should succeed since, even if we overflow the global
tonyp@2968 249 // stack, we should have definitely removed some entries from the
tonyp@2968 250 // local queue. So, there must be space on it.
tonyp@2968 251 bool success = _task_queue->push(obj);
tonyp@2968 252 assert(success, "invariant");
tonyp@2968 253 }
tonyp@2968 254
tonyp@2968 255 statsOnly( int tmp_size = _task_queue->size();
tonyp@2973 256 if (tmp_size > _local_max_size) {
tonyp@2968 257 _local_max_size = tmp_size;
tonyp@2973 258 }
tonyp@2968 259 ++_local_pushes );
tonyp@2968 260 }
tonyp@2968 261
tonyp@2968 262 // This determines whether the method below will check both the local
tonyp@2968 263 // and global fingers when determining whether to push on the stack a
tonyp@2968 264 // gray object (value 1) or whether it will only check the global one
tonyp@2968 265 // (value 0). The tradeoffs are that the former will be a bit more
tonyp@2968 266 // accurate and possibly push less on the stack, but it might also be
tonyp@2968 267 // a little bit slower.
tonyp@2968 268
tonyp@2968 269 #define _CHECK_BOTH_FINGERS_ 1
tonyp@2968 270
tonyp@2968 271 inline void CMTask::deal_with_reference(oop obj) {
tonyp@2968 272 if (_cm->verbose_high()) {
johnc@4173 273 gclog_or_tty->print_cr("[%u] we're dealing with reference = "PTR_FORMAT,
drchase@6680 274 _worker_id, p2i((void*) obj));
tonyp@2968 275 }
tonyp@2968 276
tonyp@2968 277 ++_refs_reached;
tonyp@2968 278
tonyp@2968 279 HeapWord* objAddr = (HeapWord*) obj;
tonyp@2968 280 assert(obj->is_oop_or_null(true /* ignore mark word */), "Error");
johnc@3463 281 if (_g1h->is_in_g1_reserved(objAddr)) {
tonyp@2968 282 assert(obj != NULL, "null check is implicit");
tonyp@2968 283 if (!_nextMarkBitMap->isMarked(objAddr)) {
tonyp@2968 284 // Only get the containing region if the object is not marked on the
tonyp@2968 285 // bitmap (otherwise, it's a waste of time since we won't do
tonyp@2968 286 // anything with it).
tonyp@2968 287 HeapRegion* hr = _g1h->heap_region_containing_raw(obj);
tonyp@2968 288 if (!hr->obj_allocated_since_next_marking(obj)) {
tonyp@2968 289 if (_cm->verbose_high()) {
johnc@4173 290 gclog_or_tty->print_cr("[%u] "PTR_FORMAT" is not considered marked",
drchase@6680 291 _worker_id, p2i((void*) obj));
tonyp@2968 292 }
tonyp@2968 293
tonyp@2968 294 // we need to mark it first
johnc@3463 295 if (_cm->par_mark_and_count(obj, hr, _marked_bytes_array, _card_bm)) {
tonyp@2968 296 // No OrderAccess:store_load() is needed. It is implicit in the
johnc@3463 297 // CAS done in CMBitMap::parMark() call in the routine above.
tonyp@2968 298 HeapWord* global_finger = _cm->finger();
tonyp@2968 299
tonyp@2968 300 #if _CHECK_BOTH_FINGERS_
tonyp@2968 301 // we will check both the local and global fingers
tonyp@2968 302
tonyp@2968 303 if (_finger != NULL && objAddr < _finger) {
tonyp@2968 304 if (_cm->verbose_high()) {
johnc@4173 305 gclog_or_tty->print_cr("[%u] below the local finger ("PTR_FORMAT"), "
drchase@6680 306 "pushing it", _worker_id, p2i(_finger));
tonyp@2968 307 }
tonyp@2968 308 push(obj);
tonyp@2968 309 } else if (_curr_region != NULL && objAddr < _region_limit) {
tonyp@2968 310 // do nothing
tonyp@2968 311 } else if (objAddr < global_finger) {
tonyp@2968 312 // Notice that the global finger might be moving forward
tonyp@2968 313 // concurrently. This is not a problem. In the worst case, we
tonyp@2968 314 // mark the object while it is above the global finger and, by
tonyp@2968 315 // the time we read the global finger, it has moved forward
tonyp@2968 316 // passed this object. In this case, the object will probably
tonyp@2968 317 // be visited when a task is scanning the region and will also
tonyp@2968 318 // be pushed on the stack. So, some duplicate work, but no
tonyp@2968 319 // correctness problems.
tonyp@2968 320
tonyp@2968 321 if (_cm->verbose_high()) {
johnc@4173 322 gclog_or_tty->print_cr("[%u] below the global finger "
tonyp@2968 323 "("PTR_FORMAT"), pushing it",
drchase@6680 324 _worker_id, p2i(global_finger));
tonyp@2968 325 }
tonyp@2968 326 push(obj);
tonyp@2968 327 } else {
tonyp@2968 328 // do nothing
tonyp@2968 329 }
tonyp@2968 330 #else // _CHECK_BOTH_FINGERS_
tonyp@2968 331 // we will only check the global finger
tonyp@2968 332
tonyp@2968 333 if (objAddr < global_finger) {
tonyp@2968 334 // see long comment above
tonyp@2968 335
tonyp@2968 336 if (_cm->verbose_high()) {
johnc@4173 337 gclog_or_tty->print_cr("[%u] below the global finger "
tonyp@2968 338 "("PTR_FORMAT"), pushing it",
drchase@6680 339 _worker_id, p2i(global_finger));
tonyp@2968 340 }
tonyp@2968 341 push(obj);
tonyp@2968 342 }
tonyp@2968 343 #endif // _CHECK_BOTH_FINGERS_
tonyp@2968 344 }
tonyp@2968 345 }
tonyp@2968 346 }
tonyp@2968 347 }
tonyp@2968 348 }
tonyp@2968 349
tonyp@3416 350 inline void ConcurrentMark::markPrev(oop p) {
tonyp@3416 351 assert(!_prevMarkBitMap->isMarked((HeapWord*) p), "sanity");
tonyp@3416 352 // Note we are overriding the read-only view of the prev map here, via
tonyp@3416 353 // the cast.
tonyp@3416 354 ((CMBitMap*)_prevMarkBitMap)->mark((HeapWord*) p);
tonyp@3416 355 }
tonyp@3416 356
tonyp@3464 357 inline void ConcurrentMark::grayRoot(oop obj, size_t word_size,
tonyp@3464 358 uint worker_id, HeapRegion* hr) {
tonyp@3464 359 assert(obj != NULL, "pre-condition");
tonyp@3416 360 HeapWord* addr = (HeapWord*) obj;
tonyp@3464 361 if (hr == NULL) {
tonyp@3464 362 hr = _g1h->heap_region_containing_raw(addr);
tonyp@3464 363 } else {
tonyp@3464 364 assert(hr->is_in(addr), "pre-condition");
tonyp@3464 365 }
tonyp@3464 366 assert(hr != NULL, "sanity");
tonyp@3464 367 // Given that we're looking for a region that contains an object
tonyp@3464 368 // header it's impossible to get back a HC region.
tonyp@3464 369 assert(!hr->continuesHumongous(), "sanity");
tonyp@3416 370
tonyp@3416 371 // We cannot assert that word_size == obj->size() given that obj
tonyp@3416 372 // might not be in a consistent state (another thread might be in
tonyp@3416 373 // the process of copying it). So the best thing we can do is to
tonyp@3416 374 // assert that word_size is under an upper bound which is its
tonyp@3416 375 // containing region's capacity.
tonyp@3416 376 assert(word_size * HeapWordSize <= hr->capacity(),
tonyp@3416 377 err_msg("size: "SIZE_FORMAT" capacity: "SIZE_FORMAT" "HR_FORMAT,
tonyp@3416 378 word_size * HeapWordSize, hr->capacity(),
tonyp@3416 379 HR_FORMAT_PARAMS(hr)));
tonyp@3416 380
tonyp@3464 381 if (addr < hr->next_top_at_mark_start()) {
tonyp@3464 382 if (!_nextMarkBitMap->isMarked(addr)) {
tonyp@3464 383 par_mark_and_count(obj, word_size, hr, worker_id);
tonyp@3464 384 }
tonyp@3416 385 }
tonyp@3416 386 }
tonyp@3416 387
tonyp@2968 388 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTMARK_INLINE_HPP

mercurial