src/share/vm/gc_implementation/g1/g1BlockOffsetTable.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 2241
72a161e62cc4
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, 2008, 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/_g1BlockOffsetTable.cpp.incl"
ysr@777 27
ysr@777 28 //////////////////////////////////////////////////////////////////////
ysr@777 29 // G1BlockOffsetSharedArray
ysr@777 30 //////////////////////////////////////////////////////////////////////
ysr@777 31
ysr@777 32 G1BlockOffsetSharedArray::G1BlockOffsetSharedArray(MemRegion reserved,
ysr@777 33 size_t init_word_size) :
ysr@777 34 _reserved(reserved), _end(NULL)
ysr@777 35 {
ysr@777 36 size_t size = compute_size(reserved.word_size());
ysr@777 37 ReservedSpace rs(ReservedSpace::allocation_align_size_up(size));
ysr@777 38 if (!rs.is_reserved()) {
ysr@777 39 vm_exit_during_initialization("Could not reserve enough space for heap offset array");
ysr@777 40 }
ysr@777 41 if (!_vs.initialize(rs, 0)) {
ysr@777 42 vm_exit_during_initialization("Could not reserve enough space for heap offset array");
ysr@777 43 }
ysr@777 44 _offset_array = (u_char*)_vs.low_boundary();
ysr@777 45 resize(init_word_size);
ysr@777 46 if (TraceBlockOffsetTable) {
ysr@777 47 gclog_or_tty->print_cr("G1BlockOffsetSharedArray::G1BlockOffsetSharedArray: ");
ysr@777 48 gclog_or_tty->print_cr(" "
ysr@777 49 " rs.base(): " INTPTR_FORMAT
ysr@777 50 " rs.size(): " INTPTR_FORMAT
ysr@777 51 " rs end(): " INTPTR_FORMAT,
ysr@777 52 rs.base(), rs.size(), rs.base() + rs.size());
ysr@777 53 gclog_or_tty->print_cr(" "
ysr@777 54 " _vs.low_boundary(): " INTPTR_FORMAT
ysr@777 55 " _vs.high_boundary(): " INTPTR_FORMAT,
ysr@777 56 _vs.low_boundary(),
ysr@777 57 _vs.high_boundary());
ysr@777 58 }
ysr@777 59 }
ysr@777 60
ysr@777 61 void G1BlockOffsetSharedArray::resize(size_t new_word_size) {
ysr@777 62 assert(new_word_size <= _reserved.word_size(), "Resize larger than reserved");
ysr@777 63 size_t new_size = compute_size(new_word_size);
ysr@777 64 size_t old_size = _vs.committed_size();
ysr@777 65 size_t delta;
ysr@777 66 char* high = _vs.high();
ysr@777 67 _end = _reserved.start() + new_word_size;
ysr@777 68 if (new_size > old_size) {
ysr@777 69 delta = ReservedSpace::page_align_size_up(new_size - old_size);
ysr@777 70 assert(delta > 0, "just checking");
ysr@777 71 if (!_vs.expand_by(delta)) {
ysr@777 72 // Do better than this for Merlin
ysr@777 73 vm_exit_out_of_memory(delta, "offset table expansion");
ysr@777 74 }
ysr@777 75 assert(_vs.high() == high + delta, "invalid expansion");
ysr@777 76 // Initialization of the contents is left to the
ysr@777 77 // G1BlockOffsetArray that uses it.
ysr@777 78 } else {
ysr@777 79 delta = ReservedSpace::page_align_size_down(old_size - new_size);
ysr@777 80 if (delta == 0) return;
ysr@777 81 _vs.shrink_by(delta);
ysr@777 82 assert(_vs.high() == high - delta, "invalid expansion");
ysr@777 83 }
ysr@777 84 }
ysr@777 85
ysr@777 86 bool G1BlockOffsetSharedArray::is_card_boundary(HeapWord* p) const {
ysr@777 87 assert(p >= _reserved.start(), "just checking");
ysr@777 88 size_t delta = pointer_delta(p, _reserved.start());
ysr@777 89 return (delta & right_n_bits(LogN_words)) == (size_t)NoBits;
ysr@777 90 }
ysr@777 91
ysr@777 92
ysr@777 93 //////////////////////////////////////////////////////////////////////
ysr@777 94 // G1BlockOffsetArray
ysr@777 95 //////////////////////////////////////////////////////////////////////
ysr@777 96
ysr@777 97 G1BlockOffsetArray::G1BlockOffsetArray(G1BlockOffsetSharedArray* array,
ysr@777 98 MemRegion mr, bool init_to_zero) :
ysr@777 99 G1BlockOffsetTable(mr.start(), mr.end()),
ysr@777 100 _unallocated_block(_bottom),
ysr@777 101 _array(array), _csp(NULL),
ysr@777 102 _init_to_zero(init_to_zero) {
ysr@777 103 assert(_bottom <= _end, "arguments out of order");
ysr@777 104 if (!_init_to_zero) {
ysr@777 105 // initialize cards to point back to mr.start()
ysr@777 106 set_remainder_to_point_to_start(mr.start() + N_words, mr.end());
ysr@777 107 _array->set_offset_array(0, 0); // set first card to 0
ysr@777 108 }
ysr@777 109 }
ysr@777 110
ysr@777 111 void G1BlockOffsetArray::set_space(Space* sp) {
ysr@777 112 _sp = sp;
ysr@777 113 _csp = sp->toContiguousSpace();
ysr@777 114 }
ysr@777 115
ysr@777 116 // The arguments follow the normal convention of denoting
ysr@777 117 // a right-open interval: [start, end)
ysr@777 118 void
ysr@777 119 G1BlockOffsetArray:: set_remainder_to_point_to_start(HeapWord* start, HeapWord* end) {
ysr@777 120
ysr@777 121 if (start >= end) {
ysr@777 122 // The start address is equal to the end address (or to
ysr@777 123 // the right of the end address) so there are not cards
ysr@777 124 // that need to be updated..
ysr@777 125 return;
ysr@777 126 }
ysr@777 127
ysr@777 128 // Write the backskip value for each region.
ysr@777 129 //
ysr@777 130 // offset
ysr@777 131 // card 2nd 3rd
ysr@777 132 // | +- 1st | |
ysr@777 133 // v v v v
ysr@777 134 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-
ysr@777 135 // |x|0|0|0|0|0|0|0|1|1|1|1|1|1| ... |1|1|1|1|2|2|2|2|2|2| ...
ysr@777 136 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-
ysr@777 137 // 11 19 75
ysr@777 138 // 12
ysr@777 139 //
ysr@777 140 // offset card is the card that points to the start of an object
ysr@777 141 // x - offset value of offset card
ysr@777 142 // 1st - start of first logarithmic region
ysr@777 143 // 0 corresponds to logarithmic value N_words + 0 and 2**(3 * 0) = 1
ysr@777 144 // 2nd - start of second logarithmic region
ysr@777 145 // 1 corresponds to logarithmic value N_words + 1 and 2**(3 * 1) = 8
ysr@777 146 // 3rd - start of third logarithmic region
ysr@777 147 // 2 corresponds to logarithmic value N_words + 2 and 2**(3 * 2) = 64
ysr@777 148 //
ysr@777 149 // integer below the block offset entry is an example of
ysr@777 150 // the index of the entry
ysr@777 151 //
ysr@777 152 // Given an address,
ysr@777 153 // Find the index for the address
ysr@777 154 // Find the block offset table entry
ysr@777 155 // Convert the entry to a back slide
ysr@777 156 // (e.g., with today's, offset = 0x81 =>
ysr@777 157 // back slip = 2**(3*(0x81 - N_words)) = 2**3) = 8
ysr@777 158 // Move back N (e.g., 8) entries and repeat with the
ysr@777 159 // value of the new entry
ysr@777 160 //
ysr@777 161 size_t start_card = _array->index_for(start);
ysr@777 162 size_t end_card = _array->index_for(end-1);
ysr@777 163 assert(start ==_array->address_for_index(start_card), "Precondition");
ysr@777 164 assert(end ==_array->address_for_index(end_card)+N_words, "Precondition");
ysr@777 165 set_remainder_to_point_to_start_incl(start_card, end_card); // closed interval
ysr@777 166 }
ysr@777 167
ysr@777 168 // Unlike the normal convention in this code, the argument here denotes
ysr@777 169 // a closed, inclusive interval: [start_card, end_card], cf set_remainder_to_point_to_start()
ysr@777 170 // above.
ysr@777 171 void
ysr@777 172 G1BlockOffsetArray::set_remainder_to_point_to_start_incl(size_t start_card, size_t end_card) {
ysr@777 173 if (start_card > end_card) {
ysr@777 174 return;
ysr@777 175 }
ysr@777 176 assert(start_card > _array->index_for(_bottom), "Cannot be first card");
ysr@777 177 assert(_array->offset_array(start_card-1) <= N_words,
ysr@777 178 "Offset card has an unexpected value");
ysr@777 179 size_t start_card_for_region = start_card;
ysr@777 180 u_char offset = max_jubyte;
ysr@777 181 for (int i = 0; i < BlockOffsetArray::N_powers; i++) {
ysr@777 182 // -1 so that the the card with the actual offset is counted. Another -1
ysr@777 183 // so that the reach ends in this region and not at the start
ysr@777 184 // of the next.
ysr@777 185 size_t reach = start_card - 1 + (BlockOffsetArray::power_to_cards_back(i+1) - 1);
ysr@777 186 offset = N_words + i;
ysr@777 187 if (reach >= end_card) {
ysr@777 188 _array->set_offset_array(start_card_for_region, end_card, offset);
ysr@777 189 start_card_for_region = reach + 1;
ysr@777 190 break;
ysr@777 191 }
ysr@777 192 _array->set_offset_array(start_card_for_region, reach, offset);
ysr@777 193 start_card_for_region = reach + 1;
ysr@777 194 }
ysr@777 195 assert(start_card_for_region > end_card, "Sanity check");
ysr@777 196 DEBUG_ONLY(check_all_cards(start_card, end_card);)
ysr@777 197 }
ysr@777 198
ysr@777 199 // The block [blk_start, blk_end) has been allocated;
ysr@777 200 // adjust the block offset table to represent this information;
ysr@777 201 // right-open interval: [blk_start, blk_end)
ysr@777 202 void
ysr@777 203 G1BlockOffsetArray::alloc_block(HeapWord* blk_start, HeapWord* blk_end) {
ysr@777 204 mark_block(blk_start, blk_end);
ysr@777 205 allocated(blk_start, blk_end);
ysr@777 206 }
ysr@777 207
ysr@777 208 // Adjust BOT to show that a previously whole block has been split
ysr@777 209 // into two.
ysr@777 210 void G1BlockOffsetArray::split_block(HeapWord* blk, size_t blk_size,
ysr@777 211 size_t left_blk_size) {
ysr@777 212 // Verify that the BOT shows [blk, blk + blk_size) to be one block.
ysr@777 213 verify_single_block(blk, blk_size);
ysr@777 214 // Update the BOT to indicate that [blk + left_blk_size, blk + blk_size)
ysr@777 215 // is one single block.
ysr@777 216 mark_block(blk + left_blk_size, blk + blk_size);
ysr@777 217 }
ysr@777 218
ysr@777 219
ysr@777 220 // Action_mark - update the BOT for the block [blk_start, blk_end).
ysr@777 221 // Current typical use is for splitting a block.
ysr@777 222 // Action_single - udpate the BOT for an allocation.
ysr@777 223 // Action_verify - BOT verification.
ysr@777 224 void G1BlockOffsetArray::do_block_internal(HeapWord* blk_start,
ysr@777 225 HeapWord* blk_end,
ysr@777 226 Action action) {
ysr@777 227 assert(Universe::heap()->is_in_reserved(blk_start),
ysr@777 228 "reference must be into the heap");
ysr@777 229 assert(Universe::heap()->is_in_reserved(blk_end-1),
ysr@777 230 "limit must be within the heap");
ysr@777 231 // This is optimized to make the test fast, assuming we only rarely
ysr@777 232 // cross boundaries.
ysr@777 233 uintptr_t end_ui = (uintptr_t)(blk_end - 1);
ysr@777 234 uintptr_t start_ui = (uintptr_t)blk_start;
ysr@777 235 // Calculate the last card boundary preceding end of blk
ysr@777 236 intptr_t boundary_before_end = (intptr_t)end_ui;
ysr@777 237 clear_bits(boundary_before_end, right_n_bits(LogN));
ysr@777 238 if (start_ui <= (uintptr_t)boundary_before_end) {
ysr@777 239 // blk starts at or crosses a boundary
ysr@777 240 // Calculate index of card on which blk begins
ysr@777 241 size_t start_index = _array->index_for(blk_start);
ysr@777 242 // Index of card on which blk ends
ysr@777 243 size_t end_index = _array->index_for(blk_end - 1);
ysr@777 244 // Start address of card on which blk begins
ysr@777 245 HeapWord* boundary = _array->address_for_index(start_index);
ysr@777 246 assert(boundary <= blk_start, "blk should start at or after boundary");
ysr@777 247 if (blk_start != boundary) {
ysr@777 248 // blk starts strictly after boundary
ysr@777 249 // adjust card boundary and start_index forward to next card
ysr@777 250 boundary += N_words;
ysr@777 251 start_index++;
ysr@777 252 }
ysr@777 253 assert(start_index <= end_index, "monotonicity of index_for()");
ysr@777 254 assert(boundary <= (HeapWord*)boundary_before_end, "tautology");
ysr@777 255 switch (action) {
ysr@777 256 case Action_mark: {
ysr@777 257 if (init_to_zero()) {
ysr@777 258 _array->set_offset_array(start_index, boundary, blk_start);
ysr@777 259 break;
ysr@777 260 } // Else fall through to the next case
ysr@777 261 }
ysr@777 262 case Action_single: {
ysr@777 263 _array->set_offset_array(start_index, boundary, blk_start);
ysr@777 264 // We have finished marking the "offset card". We need to now
ysr@777 265 // mark the subsequent cards that this blk spans.
ysr@777 266 if (start_index < end_index) {
ysr@777 267 HeapWord* rem_st = _array->address_for_index(start_index) + N_words;
ysr@777 268 HeapWord* rem_end = _array->address_for_index(end_index) + N_words;
ysr@777 269 set_remainder_to_point_to_start(rem_st, rem_end);
ysr@777 270 }
ysr@777 271 break;
ysr@777 272 }
ysr@777 273 case Action_check: {
ysr@777 274 _array->check_offset_array(start_index, boundary, blk_start);
ysr@777 275 // We have finished checking the "offset card". We need to now
ysr@777 276 // check the subsequent cards that this blk spans.
ysr@777 277 check_all_cards(start_index + 1, end_index);
ysr@777 278 break;
ysr@777 279 }
ysr@777 280 default:
ysr@777 281 ShouldNotReachHere();
ysr@777 282 }
ysr@777 283 }
ysr@777 284 }
ysr@777 285
ysr@777 286 // The card-interval [start_card, end_card] is a closed interval; this
ysr@777 287 // is an expensive check -- use with care and only under protection of
ysr@777 288 // suitable flag.
ysr@777 289 void G1BlockOffsetArray::check_all_cards(size_t start_card, size_t end_card) const {
ysr@777 290
ysr@777 291 if (end_card < start_card) {
ysr@777 292 return;
ysr@777 293 }
ysr@777 294 guarantee(_array->offset_array(start_card) == N_words, "Wrong value in second card");
ysr@777 295 for (size_t c = start_card + 1; c <= end_card; c++ /* yeah! */) {
ysr@777 296 u_char entry = _array->offset_array(c);
ysr@777 297 if (c - start_card > BlockOffsetArray::power_to_cards_back(1)) {
ysr@777 298 guarantee(entry > N_words, "Should be in logarithmic region");
ysr@777 299 }
ysr@777 300 size_t backskip = BlockOffsetArray::entry_to_cards_back(entry);
ysr@777 301 size_t landing_card = c - backskip;
ysr@777 302 guarantee(landing_card >= (start_card - 1), "Inv");
ysr@777 303 if (landing_card >= start_card) {
ysr@777 304 guarantee(_array->offset_array(landing_card) <= entry, "monotonicity");
ysr@777 305 } else {
ysr@777 306 guarantee(landing_card == start_card - 1, "Tautology");
ysr@777 307 guarantee(_array->offset_array(landing_card) <= N_words, "Offset value");
ysr@777 308 }
ysr@777 309 }
ysr@777 310 }
ysr@777 311
ysr@777 312 // The range [blk_start, blk_end) represents a single contiguous block
ysr@777 313 // of storage; modify the block offset table to represent this
ysr@777 314 // information; Right-open interval: [blk_start, blk_end)
ysr@777 315 // NOTE: this method does _not_ adjust _unallocated_block.
ysr@777 316 void
ysr@777 317 G1BlockOffsetArray::single_block(HeapWord* blk_start, HeapWord* blk_end) {
ysr@777 318 do_block_internal(blk_start, blk_end, Action_single);
ysr@777 319 }
ysr@777 320
ysr@777 321 // Mark the BOT such that if [blk_start, blk_end) straddles a card
ysr@777 322 // boundary, the card following the first such boundary is marked
ysr@777 323 // with the appropriate offset.
ysr@777 324 // NOTE: this method does _not_ adjust _unallocated_block or
ysr@777 325 // any cards subsequent to the first one.
ysr@777 326 void
ysr@777 327 G1BlockOffsetArray::mark_block(HeapWord* blk_start, HeapWord* blk_end) {
ysr@777 328 do_block_internal(blk_start, blk_end, Action_mark);
ysr@777 329 }
ysr@777 330
ysr@777 331 void G1BlockOffsetArray::join_blocks(HeapWord* blk1, HeapWord* blk2) {
ysr@777 332 HeapWord* blk1_start = Universe::heap()->block_start(blk1);
ysr@777 333 HeapWord* blk2_start = Universe::heap()->block_start(blk2);
ysr@777 334 assert(blk1 == blk1_start && blk2 == blk2_start,
ysr@777 335 "Must be block starts.");
ysr@777 336 assert(blk1 + _sp->block_size(blk1) == blk2, "Must be contiguous.");
ysr@777 337 size_t blk1_start_index = _array->index_for(blk1);
ysr@777 338 size_t blk2_start_index = _array->index_for(blk2);
ysr@777 339 assert(blk1_start_index <= blk2_start_index, "sanity");
ysr@777 340 HeapWord* blk2_card_start = _array->address_for_index(blk2_start_index);
ysr@777 341 if (blk2 == blk2_card_start) {
ysr@777 342 // blk2 starts a card. Does blk1 start on the prevous card, or futher
ysr@777 343 // back?
ysr@777 344 assert(blk1_start_index < blk2_start_index, "must be lower card.");
ysr@777 345 if (blk1_start_index + 1 == blk2_start_index) {
ysr@777 346 // previous card; new value for blk2 card is size of blk1.
ysr@777 347 _array->set_offset_array(blk2_start_index, (u_char) _sp->block_size(blk1));
ysr@777 348 } else {
ysr@777 349 // Earlier card; go back a card.
ysr@777 350 _array->set_offset_array(blk2_start_index, N_words);
ysr@777 351 }
ysr@777 352 } else {
ysr@777 353 // blk2 does not start a card. Does it cross a card? If not, nothing
ysr@777 354 // to do.
ysr@777 355 size_t blk2_end_index =
ysr@777 356 _array->index_for(blk2 + _sp->block_size(blk2) - 1);
ysr@777 357 assert(blk2_end_index >= blk2_start_index, "sanity");
ysr@777 358 if (blk2_end_index > blk2_start_index) {
ysr@777 359 // Yes, it crosses a card. The value for the next card must change.
ysr@777 360 if (blk1_start_index + 1 == blk2_start_index) {
ysr@777 361 // previous card; new value for second blk2 card is size of blk1.
ysr@777 362 _array->set_offset_array(blk2_start_index + 1,
ysr@777 363 (u_char) _sp->block_size(blk1));
ysr@777 364 } else {
ysr@777 365 // Earlier card; go back a card.
ysr@777 366 _array->set_offset_array(blk2_start_index + 1, N_words);
ysr@777 367 }
ysr@777 368 }
ysr@777 369 }
ysr@777 370 }
ysr@777 371
ysr@777 372 HeapWord* G1BlockOffsetArray::block_start_unsafe(const void* addr) {
ysr@777 373 assert(_bottom <= addr && addr < _end,
ysr@777 374 "addr must be covered by this Array");
ysr@777 375 // Must read this exactly once because it can be modified by parallel
ysr@777 376 // allocation.
ysr@777 377 HeapWord* ub = _unallocated_block;
ysr@777 378 if (BlockOffsetArrayUseUnallocatedBlock && addr >= ub) {
ysr@777 379 assert(ub < _end, "tautology (see above)");
ysr@777 380 return ub;
ysr@777 381 }
ysr@777 382 // Otherwise, find the block start using the table.
ysr@777 383 HeapWord* q = block_at_or_preceding(addr, false, 0);
ysr@777 384 return forward_to_block_containing_addr(q, addr);
ysr@777 385 }
ysr@777 386
ysr@777 387 // This duplicates a little code from the above: unavoidable.
ysr@777 388 HeapWord*
ysr@777 389 G1BlockOffsetArray::block_start_unsafe_const(const void* addr) const {
ysr@777 390 assert(_bottom <= addr && addr < _end,
ysr@777 391 "addr must be covered by this Array");
ysr@777 392 // Must read this exactly once because it can be modified by parallel
ysr@777 393 // allocation.
ysr@777 394 HeapWord* ub = _unallocated_block;
ysr@777 395 if (BlockOffsetArrayUseUnallocatedBlock && addr >= ub) {
ysr@777 396 assert(ub < _end, "tautology (see above)");
ysr@777 397 return ub;
ysr@777 398 }
ysr@777 399 // Otherwise, find the block start using the table.
ysr@777 400 HeapWord* q = block_at_or_preceding(addr, false, 0);
ysr@777 401 HeapWord* n = q + _sp->block_size(q);
ysr@777 402 return forward_to_block_containing_addr_const(q, n, addr);
ysr@777 403 }
ysr@777 404
ysr@777 405
ysr@777 406 HeapWord*
ysr@777 407 G1BlockOffsetArray::forward_to_block_containing_addr_slow(HeapWord* q,
ysr@777 408 HeapWord* n,
ysr@777 409 const void* addr) {
ysr@777 410 // We're not in the normal case. We need to handle an important subcase
ysr@777 411 // here: LAB allocation. An allocation previously recorded in the
ysr@777 412 // offset table was actually a lab allocation, and was divided into
ysr@777 413 // several objects subsequently. Fix this situation as we answer the
ysr@777 414 // query, by updating entries as we cross them.
iveresov@787 415
iveresov@787 416 // If the fist object's end q is at the card boundary. Start refining
iveresov@787 417 // with the corresponding card (the value of the entry will be basically
iveresov@787 418 // set to 0). If the object crosses the boundary -- start from the next card.
iveresov@787 419 size_t next_index = _array->index_for(n) + !_array->is_card_boundary(n);
ysr@777 420 HeapWord* next_boundary = _array->address_for_index(next_index);
ysr@777 421 if (csp() != NULL) {
ysr@777 422 if (addr >= csp()->top()) return csp()->top();
ysr@777 423 while (next_boundary < addr) {
ysr@777 424 while (n <= next_boundary) {
ysr@777 425 q = n;
ysr@777 426 oop obj = oop(q);
ysr@1280 427 if (obj->klass_or_null() == NULL) return q;
ysr@777 428 n += obj->size();
ysr@777 429 }
ysr@777 430 assert(q <= next_boundary && n > next_boundary, "Consequence of loop");
ysr@777 431 // [q, n) is the block that crosses the boundary.
ysr@777 432 alloc_block_work2(&next_boundary, &next_index, q, n);
ysr@777 433 }
ysr@777 434 } else {
ysr@777 435 while (next_boundary < addr) {
ysr@777 436 while (n <= next_boundary) {
ysr@777 437 q = n;
ysr@777 438 oop obj = oop(q);
ysr@1280 439 if (obj->klass_or_null() == NULL) return q;
ysr@777 440 n += _sp->block_size(q);
ysr@777 441 }
ysr@777 442 assert(q <= next_boundary && n > next_boundary, "Consequence of loop");
ysr@777 443 // [q, n) is the block that crosses the boundary.
ysr@777 444 alloc_block_work2(&next_boundary, &next_index, q, n);
ysr@777 445 }
ysr@777 446 }
ysr@777 447 return forward_to_block_containing_addr_const(q, n, addr);
ysr@777 448 }
ysr@777 449
ysr@777 450 HeapWord* G1BlockOffsetArray::block_start_careful(const void* addr) const {
ysr@777 451 assert(_array->offset_array(0) == 0, "objects can't cross covered areas");
ysr@777 452
ysr@777 453 assert(_bottom <= addr && addr < _end,
ysr@777 454 "addr must be covered by this Array");
ysr@777 455 // Must read this exactly once because it can be modified by parallel
ysr@777 456 // allocation.
ysr@777 457 HeapWord* ub = _unallocated_block;
ysr@777 458 if (BlockOffsetArrayUseUnallocatedBlock && addr >= ub) {
ysr@777 459 assert(ub < _end, "tautology (see above)");
ysr@777 460 return ub;
ysr@777 461 }
ysr@777 462
ysr@777 463 // Otherwise, find the block start using the table, but taking
ysr@777 464 // care (cf block_start_unsafe() above) not to parse any objects/blocks
ysr@777 465 // on the cards themsleves.
ysr@777 466 size_t index = _array->index_for(addr);
ysr@777 467 assert(_array->address_for_index(index) == addr,
ysr@777 468 "arg should be start of card");
ysr@777 469
ysr@777 470 HeapWord* q = (HeapWord*)addr;
ysr@777 471 uint offset;
ysr@777 472 do {
ysr@777 473 offset = _array->offset_array(index--);
ysr@777 474 q -= offset;
ysr@777 475 } while (offset == N_words);
ysr@777 476 assert(q <= addr, "block start should be to left of arg");
ysr@777 477 return q;
ysr@777 478 }
ysr@777 479
ysr@777 480 // Note that the committed size of the covered space may have changed,
ysr@777 481 // so the table size might also wish to change.
ysr@777 482 void G1BlockOffsetArray::resize(size_t new_word_size) {
ysr@777 483 HeapWord* new_end = _bottom + new_word_size;
ysr@777 484 if (_end < new_end && !init_to_zero()) {
ysr@777 485 // verify that the old and new boundaries are also card boundaries
ysr@777 486 assert(_array->is_card_boundary(_end),
ysr@777 487 "_end not a card boundary");
ysr@777 488 assert(_array->is_card_boundary(new_end),
ysr@777 489 "new _end would not be a card boundary");
ysr@777 490 // set all the newly added cards
ysr@777 491 _array->set_offset_array(_end, new_end, N_words);
ysr@777 492 }
ysr@777 493 _end = new_end; // update _end
ysr@777 494 }
ysr@777 495
ysr@777 496 void G1BlockOffsetArray::set_region(MemRegion mr) {
ysr@777 497 _bottom = mr.start();
ysr@777 498 _end = mr.end();
ysr@777 499 }
ysr@777 500
ysr@777 501 //
ysr@777 502 // threshold_
ysr@777 503 // | _index_
ysr@777 504 // v v
ysr@777 505 // +-------+-------+-------+-------+-------+
ysr@777 506 // | i-1 | i | i+1 | i+2 | i+3 |
ysr@777 507 // +-------+-------+-------+-------+-------+
ysr@777 508 // ( ^ ]
ysr@777 509 // block-start
ysr@777 510 //
ysr@777 511 void G1BlockOffsetArray::alloc_block_work2(HeapWord** threshold_, size_t* index_,
ysr@777 512 HeapWord* blk_start, HeapWord* blk_end) {
ysr@777 513 // For efficiency, do copy-in/copy-out.
ysr@777 514 HeapWord* threshold = *threshold_;
ysr@777 515 size_t index = *index_;
ysr@777 516
ysr@777 517 assert(blk_start != NULL && blk_end > blk_start,
ysr@777 518 "phantom block");
ysr@777 519 assert(blk_end > threshold, "should be past threshold");
jcoomes@1844 520 assert(blk_start <= threshold, "blk_start should be at or before threshold");
ysr@777 521 assert(pointer_delta(threshold, blk_start) <= N_words,
ysr@777 522 "offset should be <= BlockOffsetSharedArray::N");
ysr@777 523 assert(Universe::heap()->is_in_reserved(blk_start),
ysr@777 524 "reference must be into the heap");
ysr@777 525 assert(Universe::heap()->is_in_reserved(blk_end-1),
ysr@777 526 "limit must be within the heap");
ysr@777 527 assert(threshold == _array->_reserved.start() + index*N_words,
ysr@777 528 "index must agree with threshold");
ysr@777 529
ysr@777 530 DEBUG_ONLY(size_t orig_index = index;)
ysr@777 531
ysr@777 532 // Mark the card that holds the offset into the block. Note
ysr@777 533 // that _next_offset_index and _next_offset_threshold are not
ysr@777 534 // updated until the end of this method.
ysr@777 535 _array->set_offset_array(index, threshold, blk_start);
ysr@777 536
ysr@777 537 // We need to now mark the subsequent cards that this blk spans.
ysr@777 538
ysr@777 539 // Index of card on which blk ends.
ysr@777 540 size_t end_index = _array->index_for(blk_end - 1);
ysr@777 541
ysr@777 542 // Are there more cards left to be updated?
ysr@777 543 if (index + 1 <= end_index) {
ysr@777 544 HeapWord* rem_st = _array->address_for_index(index + 1);
ysr@777 545 // Calculate rem_end this way because end_index
ysr@777 546 // may be the last valid index in the covered region.
ysr@777 547 HeapWord* rem_end = _array->address_for_index(end_index) + N_words;
ysr@777 548 set_remainder_to_point_to_start(rem_st, rem_end);
ysr@777 549 }
ysr@777 550
ysr@777 551 index = end_index + 1;
ysr@777 552 // Calculate threshold_ this way because end_index
ysr@777 553 // may be the last valid index in the covered region.
ysr@777 554 threshold = _array->address_for_index(end_index) + N_words;
ysr@777 555 assert(threshold >= blk_end, "Incorrect offset threshold");
ysr@777 556
ysr@777 557 // index_ and threshold_ updated here.
ysr@777 558 *threshold_ = threshold;
ysr@777 559 *index_ = index;
ysr@777 560
ysr@777 561 #ifdef ASSERT
ysr@777 562 // The offset can be 0 if the block starts on a boundary. That
ysr@777 563 // is checked by an assertion above.
ysr@777 564 size_t start_index = _array->index_for(blk_start);
ysr@777 565 HeapWord* boundary = _array->address_for_index(start_index);
ysr@777 566 assert((_array->offset_array(orig_index) == 0 &&
ysr@777 567 blk_start == boundary) ||
ysr@777 568 (_array->offset_array(orig_index) > 0 &&
ysr@777 569 _array->offset_array(orig_index) <= N_words),
ysr@777 570 "offset array should have been set");
ysr@777 571 for (size_t j = orig_index + 1; j <= end_index; j++) {
ysr@777 572 assert(_array->offset_array(j) > 0 &&
ysr@777 573 _array->offset_array(j) <=
ysr@777 574 (u_char) (N_words+BlockOffsetArray::N_powers-1),
ysr@777 575 "offset array should have been set");
ysr@777 576 }
ysr@777 577 #endif
ysr@777 578 }
ysr@777 579
ysr@777 580 //////////////////////////////////////////////////////////////////////
ysr@777 581 // G1BlockOffsetArrayContigSpace
ysr@777 582 //////////////////////////////////////////////////////////////////////
ysr@777 583
ysr@777 584 HeapWord*
ysr@777 585 G1BlockOffsetArrayContigSpace::block_start_unsafe(const void* addr) {
ysr@777 586 assert(_bottom <= addr && addr < _end,
ysr@777 587 "addr must be covered by this Array");
ysr@777 588 HeapWord* q = block_at_or_preceding(addr, true, _next_offset_index-1);
ysr@777 589 return forward_to_block_containing_addr(q, addr);
ysr@777 590 }
ysr@777 591
ysr@777 592 HeapWord*
ysr@777 593 G1BlockOffsetArrayContigSpace::
ysr@777 594 block_start_unsafe_const(const void* addr) const {
ysr@777 595 assert(_bottom <= addr && addr < _end,
ysr@777 596 "addr must be covered by this Array");
ysr@777 597 HeapWord* q = block_at_or_preceding(addr, true, _next_offset_index-1);
ysr@777 598 HeapWord* n = q + _sp->block_size(q);
ysr@777 599 return forward_to_block_containing_addr_const(q, n, addr);
ysr@777 600 }
ysr@777 601
ysr@777 602 G1BlockOffsetArrayContigSpace::
ysr@777 603 G1BlockOffsetArrayContigSpace(G1BlockOffsetSharedArray* array,
ysr@777 604 MemRegion mr) :
ysr@777 605 G1BlockOffsetArray(array, mr, true)
ysr@777 606 {
ysr@777 607 _next_offset_threshold = NULL;
ysr@777 608 _next_offset_index = 0;
ysr@777 609 }
ysr@777 610
ysr@777 611 HeapWord* G1BlockOffsetArrayContigSpace::initialize_threshold() {
ysr@777 612 assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
ysr@777 613 "just checking");
ysr@777 614 _next_offset_index = _array->index_for(_bottom);
ysr@777 615 _next_offset_index++;
ysr@777 616 _next_offset_threshold =
ysr@777 617 _array->address_for_index(_next_offset_index);
ysr@777 618 return _next_offset_threshold;
ysr@777 619 }
ysr@777 620
ysr@777 621 void G1BlockOffsetArrayContigSpace::zero_bottom_entry() {
ysr@777 622 assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
ysr@777 623 "just checking");
ysr@777 624 size_t bottom_index = _array->index_for(_bottom);
ysr@777 625 assert(_array->address_for_index(bottom_index) == _bottom,
ysr@777 626 "Precondition of call");
ysr@777 627 _array->set_offset_array(bottom_index, 0);
ysr@777 628 }

mercurial