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

changeset 0
f90c822e73f8
child 6876
710a3c8b516e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp	Wed Apr 27 01:25:04 2016 +0800
     1.3 @@ -0,0 +1,690 @@
     1.4 +/*
     1.5 + * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.23 + * or visit www.oracle.com if you need additional information or have any
    1.24 + * questions.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +#include "precompiled.hpp"
    1.29 +#include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp"
    1.30 +#include "memory/space.hpp"
    1.31 +#include "oops/oop.inline.hpp"
    1.32 +#include "runtime/java.hpp"
    1.33 +#include "services/memTracker.hpp"
    1.34 +
    1.35 +PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
    1.36 +
    1.37 +//////////////////////////////////////////////////////////////////////
    1.38 +// G1BlockOffsetSharedArray
    1.39 +//////////////////////////////////////////////////////////////////////
    1.40 +
    1.41 +G1BlockOffsetSharedArray::G1BlockOffsetSharedArray(MemRegion reserved,
    1.42 +                                                   size_t init_word_size) :
    1.43 +  _reserved(reserved), _end(NULL)
    1.44 +{
    1.45 +  size_t size = compute_size(reserved.word_size());
    1.46 +  ReservedSpace rs(ReservedSpace::allocation_align_size_up(size));
    1.47 +  if (!rs.is_reserved()) {
    1.48 +    vm_exit_during_initialization("Could not reserve enough space for heap offset array");
    1.49 +  }
    1.50 +  if (!_vs.initialize(rs, 0)) {
    1.51 +    vm_exit_during_initialization("Could not reserve enough space for heap offset array");
    1.52 +  }
    1.53 +
    1.54 +  MemTracker::record_virtual_memory_type((address)rs.base(), mtGC);
    1.55 +
    1.56 +  _offset_array = (u_char*)_vs.low_boundary();
    1.57 +  resize(init_word_size);
    1.58 +  if (TraceBlockOffsetTable) {
    1.59 +    gclog_or_tty->print_cr("G1BlockOffsetSharedArray::G1BlockOffsetSharedArray: ");
    1.60 +    gclog_or_tty->print_cr("  "
    1.61 +                  "  rs.base(): " INTPTR_FORMAT
    1.62 +                  "  rs.size(): " INTPTR_FORMAT
    1.63 +                  "  rs end(): " INTPTR_FORMAT,
    1.64 +                  rs.base(), rs.size(), rs.base() + rs.size());
    1.65 +    gclog_or_tty->print_cr("  "
    1.66 +                  "  _vs.low_boundary(): " INTPTR_FORMAT
    1.67 +                  "  _vs.high_boundary(): " INTPTR_FORMAT,
    1.68 +                  _vs.low_boundary(),
    1.69 +                  _vs.high_boundary());
    1.70 +  }
    1.71 +}
    1.72 +
    1.73 +void G1BlockOffsetSharedArray::resize(size_t new_word_size) {
    1.74 +  assert(new_word_size <= _reserved.word_size(), "Resize larger than reserved");
    1.75 +  size_t new_size = compute_size(new_word_size);
    1.76 +  size_t old_size = _vs.committed_size();
    1.77 +  size_t delta;
    1.78 +  char* high = _vs.high();
    1.79 +  _end = _reserved.start() + new_word_size;
    1.80 +  if (new_size > old_size) {
    1.81 +    delta = ReservedSpace::page_align_size_up(new_size - old_size);
    1.82 +    assert(delta > 0, "just checking");
    1.83 +    if (!_vs.expand_by(delta)) {
    1.84 +      // Do better than this for Merlin
    1.85 +      vm_exit_out_of_memory(delta, OOM_MMAP_ERROR, "offset table expansion");
    1.86 +    }
    1.87 +    assert(_vs.high() == high + delta, "invalid expansion");
    1.88 +    // Initialization of the contents is left to the
    1.89 +    // G1BlockOffsetArray that uses it.
    1.90 +  } else {
    1.91 +    delta = ReservedSpace::page_align_size_down(old_size - new_size);
    1.92 +    if (delta == 0) return;
    1.93 +    _vs.shrink_by(delta);
    1.94 +    assert(_vs.high() == high - delta, "invalid expansion");
    1.95 +  }
    1.96 +}
    1.97 +
    1.98 +bool G1BlockOffsetSharedArray::is_card_boundary(HeapWord* p) const {
    1.99 +  assert(p >= _reserved.start(), "just checking");
   1.100 +  size_t delta = pointer_delta(p, _reserved.start());
   1.101 +  return (delta & right_n_bits(LogN_words)) == (size_t)NoBits;
   1.102 +}
   1.103 +
   1.104 +
   1.105 +//////////////////////////////////////////////////////////////////////
   1.106 +// G1BlockOffsetArray
   1.107 +//////////////////////////////////////////////////////////////////////
   1.108 +
   1.109 +G1BlockOffsetArray::G1BlockOffsetArray(G1BlockOffsetSharedArray* array,
   1.110 +                                       MemRegion mr, bool init_to_zero) :
   1.111 +  G1BlockOffsetTable(mr.start(), mr.end()),
   1.112 +  _unallocated_block(_bottom),
   1.113 +  _array(array), _csp(NULL),
   1.114 +  _init_to_zero(init_to_zero) {
   1.115 +  assert(_bottom <= _end, "arguments out of order");
   1.116 +  if (!_init_to_zero) {
   1.117 +    // initialize cards to point back to mr.start()
   1.118 +    set_remainder_to_point_to_start(mr.start() + N_words, mr.end());
   1.119 +    _array->set_offset_array(0, 0);  // set first card to 0
   1.120 +  }
   1.121 +}
   1.122 +
   1.123 +void G1BlockOffsetArray::set_space(Space* sp) {
   1.124 +  _sp = sp;
   1.125 +  _csp = sp->toContiguousSpace();
   1.126 +}
   1.127 +
   1.128 +// The arguments follow the normal convention of denoting
   1.129 +// a right-open interval: [start, end)
   1.130 +void
   1.131 +G1BlockOffsetArray:: set_remainder_to_point_to_start(HeapWord* start, HeapWord* end) {
   1.132 +
   1.133 +  if (start >= end) {
   1.134 +    // The start address is equal to the end address (or to
   1.135 +    // the right of the end address) so there are not cards
   1.136 +    // that need to be updated..
   1.137 +    return;
   1.138 +  }
   1.139 +
   1.140 +  // Write the backskip value for each region.
   1.141 +  //
   1.142 +  //    offset
   1.143 +  //    card             2nd                       3rd
   1.144 +  //     | +- 1st        |                         |
   1.145 +  //     v v             v                         v
   1.146 +  //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+-+-+-
   1.147 +  //    |x|0|0|0|0|0|0|0|1|1|1|1|1|1| ... |1|1|1|1|2|2|2|2|2|2| ...
   1.148 +  //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+-+-+-
   1.149 +  //    11              19                        75
   1.150 +  //      12
   1.151 +  //
   1.152 +  //    offset card is the card that points to the start of an object
   1.153 +  //      x - offset value of offset card
   1.154 +  //    1st - start of first logarithmic region
   1.155 +  //      0 corresponds to logarithmic value N_words + 0 and 2**(3 * 0) = 1
   1.156 +  //    2nd - start of second logarithmic region
   1.157 +  //      1 corresponds to logarithmic value N_words + 1 and 2**(3 * 1) = 8
   1.158 +  //    3rd - start of third logarithmic region
   1.159 +  //      2 corresponds to logarithmic value N_words + 2 and 2**(3 * 2) = 64
   1.160 +  //
   1.161 +  //    integer below the block offset entry is an example of
   1.162 +  //    the index of the entry
   1.163 +  //
   1.164 +  //    Given an address,
   1.165 +  //      Find the index for the address
   1.166 +  //      Find the block offset table entry
   1.167 +  //      Convert the entry to a back slide
   1.168 +  //        (e.g., with today's, offset = 0x81 =>
   1.169 +  //          back slip = 2**(3*(0x81 - N_words)) = 2**3) = 8
   1.170 +  //      Move back N (e.g., 8) entries and repeat with the
   1.171 +  //        value of the new entry
   1.172 +  //
   1.173 +  size_t start_card = _array->index_for(start);
   1.174 +  size_t end_card = _array->index_for(end-1);
   1.175 +  assert(start ==_array->address_for_index(start_card), "Precondition");
   1.176 +  assert(end ==_array->address_for_index(end_card)+N_words, "Precondition");
   1.177 +  set_remainder_to_point_to_start_incl(start_card, end_card); // closed interval
   1.178 +}
   1.179 +
   1.180 +// Unlike the normal convention in this code, the argument here denotes
   1.181 +// a closed, inclusive interval: [start_card, end_card], cf set_remainder_to_point_to_start()
   1.182 +// above.
   1.183 +void
   1.184 +G1BlockOffsetArray::set_remainder_to_point_to_start_incl(size_t start_card, size_t end_card) {
   1.185 +  if (start_card > end_card) {
   1.186 +    return;
   1.187 +  }
   1.188 +  assert(start_card > _array->index_for(_bottom), "Cannot be first card");
   1.189 +  assert(_array->offset_array(start_card-1) <= N_words,
   1.190 +         "Offset card has an unexpected value");
   1.191 +  size_t start_card_for_region = start_card;
   1.192 +  u_char offset = max_jubyte;
   1.193 +  for (int i = 0; i < BlockOffsetArray::N_powers; i++) {
   1.194 +    // -1 so that the the card with the actual offset is counted.  Another -1
   1.195 +    // so that the reach ends in this region and not at the start
   1.196 +    // of the next.
   1.197 +    size_t reach = start_card - 1 + (BlockOffsetArray::power_to_cards_back(i+1) - 1);
   1.198 +    offset = N_words + i;
   1.199 +    if (reach >= end_card) {
   1.200 +      _array->set_offset_array(start_card_for_region, end_card, offset);
   1.201 +      start_card_for_region = reach + 1;
   1.202 +      break;
   1.203 +    }
   1.204 +    _array->set_offset_array(start_card_for_region, reach, offset);
   1.205 +    start_card_for_region = reach + 1;
   1.206 +  }
   1.207 +  assert(start_card_for_region > end_card, "Sanity check");
   1.208 +  DEBUG_ONLY(check_all_cards(start_card, end_card);)
   1.209 +}
   1.210 +
   1.211 +// The block [blk_start, blk_end) has been allocated;
   1.212 +// adjust the block offset table to represent this information;
   1.213 +// right-open interval: [blk_start, blk_end)
   1.214 +void
   1.215 +G1BlockOffsetArray::alloc_block(HeapWord* blk_start, HeapWord* blk_end) {
   1.216 +  mark_block(blk_start, blk_end);
   1.217 +  allocated(blk_start, blk_end);
   1.218 +}
   1.219 +
   1.220 +// Adjust BOT to show that a previously whole block has been split
   1.221 +// into two.
   1.222 +void G1BlockOffsetArray::split_block(HeapWord* blk, size_t blk_size,
   1.223 +                                     size_t left_blk_size) {
   1.224 +  // Verify that the BOT shows [blk, blk + blk_size) to be one block.
   1.225 +  verify_single_block(blk, blk_size);
   1.226 +  // Update the BOT to indicate that [blk + left_blk_size, blk + blk_size)
   1.227 +  // is one single block.
   1.228 +  mark_block(blk + left_blk_size, blk + blk_size);
   1.229 +}
   1.230 +
   1.231 +
   1.232 +// Action_mark - update the BOT for the block [blk_start, blk_end).
   1.233 +//               Current typical use is for splitting a block.
   1.234 +// Action_single - update the BOT for an allocation.
   1.235 +// Action_verify - BOT verification.
   1.236 +void G1BlockOffsetArray::do_block_internal(HeapWord* blk_start,
   1.237 +                                           HeapWord* blk_end,
   1.238 +                                           Action action) {
   1.239 +  assert(Universe::heap()->is_in_reserved(blk_start),
   1.240 +         "reference must be into the heap");
   1.241 +  assert(Universe::heap()->is_in_reserved(blk_end-1),
   1.242 +         "limit must be within the heap");
   1.243 +  // This is optimized to make the test fast, assuming we only rarely
   1.244 +  // cross boundaries.
   1.245 +  uintptr_t end_ui = (uintptr_t)(blk_end - 1);
   1.246 +  uintptr_t start_ui = (uintptr_t)blk_start;
   1.247 +  // Calculate the last card boundary preceding end of blk
   1.248 +  intptr_t boundary_before_end = (intptr_t)end_ui;
   1.249 +  clear_bits(boundary_before_end, right_n_bits(LogN));
   1.250 +  if (start_ui <= (uintptr_t)boundary_before_end) {
   1.251 +    // blk starts at or crosses a boundary
   1.252 +    // Calculate index of card on which blk begins
   1.253 +    size_t    start_index = _array->index_for(blk_start);
   1.254 +    // Index of card on which blk ends
   1.255 +    size_t    end_index   = _array->index_for(blk_end - 1);
   1.256 +    // Start address of card on which blk begins
   1.257 +    HeapWord* boundary    = _array->address_for_index(start_index);
   1.258 +    assert(boundary <= blk_start, "blk should start at or after boundary");
   1.259 +    if (blk_start != boundary) {
   1.260 +      // blk starts strictly after boundary
   1.261 +      // adjust card boundary and start_index forward to next card
   1.262 +      boundary += N_words;
   1.263 +      start_index++;
   1.264 +    }
   1.265 +    assert(start_index <= end_index, "monotonicity of index_for()");
   1.266 +    assert(boundary <= (HeapWord*)boundary_before_end, "tautology");
   1.267 +    switch (action) {
   1.268 +      case Action_mark: {
   1.269 +        if (init_to_zero()) {
   1.270 +          _array->set_offset_array(start_index, boundary, blk_start);
   1.271 +          break;
   1.272 +        } // Else fall through to the next case
   1.273 +      }
   1.274 +      case Action_single: {
   1.275 +        _array->set_offset_array(start_index, boundary, blk_start);
   1.276 +        // We have finished marking the "offset card". We need to now
   1.277 +        // mark the subsequent cards that this blk spans.
   1.278 +        if (start_index < end_index) {
   1.279 +          HeapWord* rem_st = _array->address_for_index(start_index) + N_words;
   1.280 +          HeapWord* rem_end = _array->address_for_index(end_index) + N_words;
   1.281 +          set_remainder_to_point_to_start(rem_st, rem_end);
   1.282 +        }
   1.283 +        break;
   1.284 +      }
   1.285 +      case Action_check: {
   1.286 +        _array->check_offset_array(start_index, boundary, blk_start);
   1.287 +        // We have finished checking the "offset card". We need to now
   1.288 +        // check the subsequent cards that this blk spans.
   1.289 +        check_all_cards(start_index + 1, end_index);
   1.290 +        break;
   1.291 +      }
   1.292 +      default:
   1.293 +        ShouldNotReachHere();
   1.294 +    }
   1.295 +  }
   1.296 +}
   1.297 +
   1.298 +// The card-interval [start_card, end_card] is a closed interval; this
   1.299 +// is an expensive check -- use with care and only under protection of
   1.300 +// suitable flag.
   1.301 +void G1BlockOffsetArray::check_all_cards(size_t start_card, size_t end_card) const {
   1.302 +
   1.303 +  if (end_card < start_card) {
   1.304 +    return;
   1.305 +  }
   1.306 +  guarantee(_array->offset_array(start_card) == N_words, "Wrong value in second card");
   1.307 +  for (size_t c = start_card + 1; c <= end_card; c++ /* yeah! */) {
   1.308 +    u_char entry = _array->offset_array(c);
   1.309 +    if (c - start_card > BlockOffsetArray::power_to_cards_back(1)) {
   1.310 +      guarantee(entry > N_words,
   1.311 +                err_msg("Should be in logarithmic region - "
   1.312 +                        "entry: " UINT32_FORMAT ", "
   1.313 +                        "_array->offset_array(c): " UINT32_FORMAT ", "
   1.314 +                        "N_words: " UINT32_FORMAT,
   1.315 +                        entry, _array->offset_array(c), N_words));
   1.316 +    }
   1.317 +    size_t backskip = BlockOffsetArray::entry_to_cards_back(entry);
   1.318 +    size_t landing_card = c - backskip;
   1.319 +    guarantee(landing_card >= (start_card - 1), "Inv");
   1.320 +    if (landing_card >= start_card) {
   1.321 +      guarantee(_array->offset_array(landing_card) <= entry,
   1.322 +                err_msg("Monotonicity - landing_card offset: " UINT32_FORMAT ", "
   1.323 +                        "entry: " UINT32_FORMAT,
   1.324 +                        _array->offset_array(landing_card), entry));
   1.325 +    } else {
   1.326 +      guarantee(landing_card == start_card - 1, "Tautology");
   1.327 +      // Note that N_words is the maximum offset value
   1.328 +      guarantee(_array->offset_array(landing_card) <= N_words,
   1.329 +                err_msg("landing card offset: " UINT32_FORMAT ", "
   1.330 +                        "N_words: " UINT32_FORMAT,
   1.331 +                        _array->offset_array(landing_card), N_words));
   1.332 +    }
   1.333 +  }
   1.334 +}
   1.335 +
   1.336 +// The range [blk_start, blk_end) represents a single contiguous block
   1.337 +// of storage; modify the block offset table to represent this
   1.338 +// information; Right-open interval: [blk_start, blk_end)
   1.339 +// NOTE: this method does _not_ adjust _unallocated_block.
   1.340 +void
   1.341 +G1BlockOffsetArray::single_block(HeapWord* blk_start, HeapWord* blk_end) {
   1.342 +  do_block_internal(blk_start, blk_end, Action_single);
   1.343 +}
   1.344 +
   1.345 +// Mark the BOT such that if [blk_start, blk_end) straddles a card
   1.346 +// boundary, the card following the first such boundary is marked
   1.347 +// with the appropriate offset.
   1.348 +// NOTE: this method does _not_ adjust _unallocated_block or
   1.349 +// any cards subsequent to the first one.
   1.350 +void
   1.351 +G1BlockOffsetArray::mark_block(HeapWord* blk_start, HeapWord* blk_end) {
   1.352 +  do_block_internal(blk_start, blk_end, Action_mark);
   1.353 +}
   1.354 +
   1.355 +HeapWord* G1BlockOffsetArray::block_start_unsafe(const void* addr) {
   1.356 +  assert(_bottom <= addr && addr < _end,
   1.357 +         "addr must be covered by this Array");
   1.358 +  // Must read this exactly once because it can be modified by parallel
   1.359 +  // allocation.
   1.360 +  HeapWord* ub = _unallocated_block;
   1.361 +  if (BlockOffsetArrayUseUnallocatedBlock && addr >= ub) {
   1.362 +    assert(ub < _end, "tautology (see above)");
   1.363 +    return ub;
   1.364 +  }
   1.365 +  // Otherwise, find the block start using the table.
   1.366 +  HeapWord* q = block_at_or_preceding(addr, false, 0);
   1.367 +  return forward_to_block_containing_addr(q, addr);
   1.368 +}
   1.369 +
   1.370 +// This duplicates a little code from the above: unavoidable.
   1.371 +HeapWord*
   1.372 +G1BlockOffsetArray::block_start_unsafe_const(const void* addr) const {
   1.373 +  assert(_bottom <= addr && addr < _end,
   1.374 +         "addr must be covered by this Array");
   1.375 +  // Must read this exactly once because it can be modified by parallel
   1.376 +  // allocation.
   1.377 +  HeapWord* ub = _unallocated_block;
   1.378 +  if (BlockOffsetArrayUseUnallocatedBlock && addr >= ub) {
   1.379 +    assert(ub < _end, "tautology (see above)");
   1.380 +    return ub;
   1.381 +  }
   1.382 +  // Otherwise, find the block start using the table.
   1.383 +  HeapWord* q = block_at_or_preceding(addr, false, 0);
   1.384 +  HeapWord* n = q + _sp->block_size(q);
   1.385 +  return forward_to_block_containing_addr_const(q, n, addr);
   1.386 +}
   1.387 +
   1.388 +
   1.389 +HeapWord*
   1.390 +G1BlockOffsetArray::forward_to_block_containing_addr_slow(HeapWord* q,
   1.391 +                                                          HeapWord* n,
   1.392 +                                                          const void* addr) {
   1.393 +  // We're not in the normal case.  We need to handle an important subcase
   1.394 +  // here: LAB allocation.  An allocation previously recorded in the
   1.395 +  // offset table was actually a lab allocation, and was divided into
   1.396 +  // several objects subsequently.  Fix this situation as we answer the
   1.397 +  // query, by updating entries as we cross them.
   1.398 +
   1.399 +  // If the fist object's end q is at the card boundary. Start refining
   1.400 +  // with the corresponding card (the value of the entry will be basically
   1.401 +  // set to 0). If the object crosses the boundary -- start from the next card.
   1.402 +  size_t n_index = _array->index_for(n);
   1.403 +  size_t next_index = _array->index_for(n) + !_array->is_card_boundary(n);
   1.404 +  // Calculate a consistent next boundary.  If "n" is not at the boundary
   1.405 +  // already, step to the boundary.
   1.406 +  HeapWord* next_boundary = _array->address_for_index(n_index) +
   1.407 +                            (n_index == next_index ? 0 : N_words);
   1.408 +  assert(next_boundary <= _array->_end,
   1.409 +         err_msg("next_boundary is beyond the end of the covered region "
   1.410 +                 " next_boundary " PTR_FORMAT " _array->_end " PTR_FORMAT,
   1.411 +                 next_boundary, _array->_end));
   1.412 +  if (csp() != NULL) {
   1.413 +    if (addr >= csp()->top()) return csp()->top();
   1.414 +    while (next_boundary < addr) {
   1.415 +      while (n <= next_boundary) {
   1.416 +        q = n;
   1.417 +        oop obj = oop(q);
   1.418 +        if (obj->klass_or_null() == NULL) return q;
   1.419 +        n += obj->size();
   1.420 +      }
   1.421 +      assert(q <= next_boundary && n > next_boundary, "Consequence of loop");
   1.422 +      // [q, n) is the block that crosses the boundary.
   1.423 +      alloc_block_work2(&next_boundary, &next_index, q, n);
   1.424 +    }
   1.425 +  } else {
   1.426 +    while (next_boundary < addr) {
   1.427 +      while (n <= next_boundary) {
   1.428 +        q = n;
   1.429 +        oop obj = oop(q);
   1.430 +        if (obj->klass_or_null() == NULL) return q;
   1.431 +        n += _sp->block_size(q);
   1.432 +      }
   1.433 +      assert(q <= next_boundary && n > next_boundary, "Consequence of loop");
   1.434 +      // [q, n) is the block that crosses the boundary.
   1.435 +      alloc_block_work2(&next_boundary, &next_index, q, n);
   1.436 +    }
   1.437 +  }
   1.438 +  return forward_to_block_containing_addr_const(q, n, addr);
   1.439 +}
   1.440 +
   1.441 +HeapWord* G1BlockOffsetArray::block_start_careful(const void* addr) const {
   1.442 +  assert(_array->offset_array(0) == 0, "objects can't cross covered areas");
   1.443 +
   1.444 +  assert(_bottom <= addr && addr < _end,
   1.445 +         "addr must be covered by this Array");
   1.446 +  // Must read this exactly once because it can be modified by parallel
   1.447 +  // allocation.
   1.448 +  HeapWord* ub = _unallocated_block;
   1.449 +  if (BlockOffsetArrayUseUnallocatedBlock && addr >= ub) {
   1.450 +    assert(ub < _end, "tautology (see above)");
   1.451 +    return ub;
   1.452 +  }
   1.453 +
   1.454 +  // Otherwise, find the block start using the table, but taking
   1.455 +  // care (cf block_start_unsafe() above) not to parse any objects/blocks
   1.456 +  // on the cards themsleves.
   1.457 +  size_t index = _array->index_for(addr);
   1.458 +  assert(_array->address_for_index(index) == addr,
   1.459 +         "arg should be start of card");
   1.460 +
   1.461 +  HeapWord* q = (HeapWord*)addr;
   1.462 +  uint offset;
   1.463 +  do {
   1.464 +    offset = _array->offset_array(index--);
   1.465 +    q -= offset;
   1.466 +  } while (offset == N_words);
   1.467 +  assert(q <= addr, "block start should be to left of arg");
   1.468 +  return q;
   1.469 +}
   1.470 +
   1.471 +// Note that the committed size of the covered space may have changed,
   1.472 +// so the table size might also wish to change.
   1.473 +void G1BlockOffsetArray::resize(size_t new_word_size) {
   1.474 +  HeapWord* new_end = _bottom + new_word_size;
   1.475 +  if (_end < new_end && !init_to_zero()) {
   1.476 +    // verify that the old and new boundaries are also card boundaries
   1.477 +    assert(_array->is_card_boundary(_end),
   1.478 +           "_end not a card boundary");
   1.479 +    assert(_array->is_card_boundary(new_end),
   1.480 +           "new _end would not be a card boundary");
   1.481 +    // set all the newly added cards
   1.482 +    _array->set_offset_array(_end, new_end, N_words);
   1.483 +  }
   1.484 +  _end = new_end;  // update _end
   1.485 +}
   1.486 +
   1.487 +void G1BlockOffsetArray::set_region(MemRegion mr) {
   1.488 +  _bottom = mr.start();
   1.489 +  _end = mr.end();
   1.490 +}
   1.491 +
   1.492 +//
   1.493 +//              threshold_
   1.494 +//              |   _index_
   1.495 +//              v   v
   1.496 +//      +-------+-------+-------+-------+-------+
   1.497 +//      | i-1   |   i   | i+1   | i+2   | i+3   |
   1.498 +//      +-------+-------+-------+-------+-------+
   1.499 +//       ( ^    ]
   1.500 +//         block-start
   1.501 +//
   1.502 +void G1BlockOffsetArray::alloc_block_work2(HeapWord** threshold_, size_t* index_,
   1.503 +                                           HeapWord* blk_start, HeapWord* blk_end) {
   1.504 +  // For efficiency, do copy-in/copy-out.
   1.505 +  HeapWord* threshold = *threshold_;
   1.506 +  size_t    index = *index_;
   1.507 +
   1.508 +  assert(blk_start != NULL && blk_end > blk_start,
   1.509 +         "phantom block");
   1.510 +  assert(blk_end > threshold, "should be past threshold");
   1.511 +  assert(blk_start <= threshold, "blk_start should be at or before threshold");
   1.512 +  assert(pointer_delta(threshold, blk_start) <= N_words,
   1.513 +         "offset should be <= BlockOffsetSharedArray::N");
   1.514 +  assert(Universe::heap()->is_in_reserved(blk_start),
   1.515 +         "reference must be into the heap");
   1.516 +  assert(Universe::heap()->is_in_reserved(blk_end-1),
   1.517 +         "limit must be within the heap");
   1.518 +  assert(threshold == _array->_reserved.start() + index*N_words,
   1.519 +         "index must agree with threshold");
   1.520 +
   1.521 +  DEBUG_ONLY(size_t orig_index = index;)
   1.522 +
   1.523 +  // Mark the card that holds the offset into the block.  Note
   1.524 +  // that _next_offset_index and _next_offset_threshold are not
   1.525 +  // updated until the end of this method.
   1.526 +  _array->set_offset_array(index, threshold, blk_start);
   1.527 +
   1.528 +  // We need to now mark the subsequent cards that this blk spans.
   1.529 +
   1.530 +  // Index of card on which blk ends.
   1.531 +  size_t end_index   = _array->index_for(blk_end - 1);
   1.532 +
   1.533 +  // Are there more cards left to be updated?
   1.534 +  if (index + 1 <= end_index) {
   1.535 +    HeapWord* rem_st  = _array->address_for_index(index + 1);
   1.536 +    // Calculate rem_end this way because end_index
   1.537 +    // may be the last valid index in the covered region.
   1.538 +    HeapWord* rem_end = _array->address_for_index(end_index) +  N_words;
   1.539 +    set_remainder_to_point_to_start(rem_st, rem_end);
   1.540 +  }
   1.541 +
   1.542 +  index = end_index + 1;
   1.543 +  // Calculate threshold_ this way because end_index
   1.544 +  // may be the last valid index in the covered region.
   1.545 +  threshold = _array->address_for_index(end_index) + N_words;
   1.546 +  assert(threshold >= blk_end, "Incorrect offset threshold");
   1.547 +
   1.548 +  // index_ and threshold_ updated here.
   1.549 +  *threshold_ = threshold;
   1.550 +  *index_ = index;
   1.551 +
   1.552 +#ifdef ASSERT
   1.553 +  // The offset can be 0 if the block starts on a boundary.  That
   1.554 +  // is checked by an assertion above.
   1.555 +  size_t start_index = _array->index_for(blk_start);
   1.556 +  HeapWord* boundary = _array->address_for_index(start_index);
   1.557 +  assert((_array->offset_array(orig_index) == 0 &&
   1.558 +          blk_start == boundary) ||
   1.559 +          (_array->offset_array(orig_index) > 0 &&
   1.560 +         _array->offset_array(orig_index) <= N_words),
   1.561 +         err_msg("offset array should have been set - "
   1.562 +                  "orig_index offset: " UINT32_FORMAT ", "
   1.563 +                  "blk_start: " PTR_FORMAT ", "
   1.564 +                  "boundary: " PTR_FORMAT,
   1.565 +                  _array->offset_array(orig_index),
   1.566 +                  blk_start, boundary));
   1.567 +  for (size_t j = orig_index + 1; j <= end_index; j++) {
   1.568 +    assert(_array->offset_array(j) > 0 &&
   1.569 +           _array->offset_array(j) <=
   1.570 +             (u_char) (N_words+BlockOffsetArray::N_powers-1),
   1.571 +           err_msg("offset array should have been set - "
   1.572 +                   UINT32_FORMAT " not > 0 OR "
   1.573 +                   UINT32_FORMAT " not <= " UINT32_FORMAT,
   1.574 +                   _array->offset_array(j),
   1.575 +                   _array->offset_array(j),
   1.576 +                   (u_char) (N_words+BlockOffsetArray::N_powers-1)));
   1.577 +  }
   1.578 +#endif
   1.579 +}
   1.580 +
   1.581 +bool
   1.582 +G1BlockOffsetArray::verify_for_object(HeapWord* obj_start,
   1.583 +                                      size_t word_size) const {
   1.584 +  size_t first_card = _array->index_for(obj_start);
   1.585 +  size_t last_card = _array->index_for(obj_start + word_size - 1);
   1.586 +  if (!_array->is_card_boundary(obj_start)) {
   1.587 +    // If the object is not on a card boundary the BOT entry of the
   1.588 +    // first card should point to another object so we should not
   1.589 +    // check that one.
   1.590 +    first_card += 1;
   1.591 +  }
   1.592 +  for (size_t card = first_card; card <= last_card; card += 1) {
   1.593 +    HeapWord* card_addr = _array->address_for_index(card);
   1.594 +    HeapWord* block_start = block_start_const(card_addr);
   1.595 +    if (block_start != obj_start) {
   1.596 +      gclog_or_tty->print_cr("block start: "PTR_FORMAT" is incorrect - "
   1.597 +                             "card index: "SIZE_FORMAT" "
   1.598 +                             "card addr: "PTR_FORMAT" BOT entry: %u "
   1.599 +                             "obj: "PTR_FORMAT" word size: "SIZE_FORMAT" "
   1.600 +                             "cards: ["SIZE_FORMAT","SIZE_FORMAT"]",
   1.601 +                             block_start, card, card_addr,
   1.602 +                             _array->offset_array(card),
   1.603 +                             obj_start, word_size, first_card, last_card);
   1.604 +      return false;
   1.605 +    }
   1.606 +  }
   1.607 +  return true;
   1.608 +}
   1.609 +
   1.610 +#ifndef PRODUCT
   1.611 +void
   1.612 +G1BlockOffsetArray::print_on(outputStream* out) {
   1.613 +  size_t from_index = _array->index_for(_bottom);
   1.614 +  size_t to_index = _array->index_for(_end);
   1.615 +  out->print_cr(">> BOT for area ["PTR_FORMAT","PTR_FORMAT") "
   1.616 +                "cards ["SIZE_FORMAT","SIZE_FORMAT")",
   1.617 +                _bottom, _end, from_index, to_index);
   1.618 +  for (size_t i = from_index; i < to_index; ++i) {
   1.619 +    out->print_cr("  entry "SIZE_FORMAT_W(8)" | "PTR_FORMAT" : %3u",
   1.620 +                  i, _array->address_for_index(i),
   1.621 +                  (uint) _array->offset_array(i));
   1.622 +  }
   1.623 +}
   1.624 +#endif // !PRODUCT
   1.625 +
   1.626 +//////////////////////////////////////////////////////////////////////
   1.627 +// G1BlockOffsetArrayContigSpace
   1.628 +//////////////////////////////////////////////////////////////////////
   1.629 +
   1.630 +HeapWord*
   1.631 +G1BlockOffsetArrayContigSpace::block_start_unsafe(const void* addr) {
   1.632 +  assert(_bottom <= addr && addr < _end,
   1.633 +         "addr must be covered by this Array");
   1.634 +  HeapWord* q = block_at_or_preceding(addr, true, _next_offset_index-1);
   1.635 +  return forward_to_block_containing_addr(q, addr);
   1.636 +}
   1.637 +
   1.638 +HeapWord*
   1.639 +G1BlockOffsetArrayContigSpace::
   1.640 +block_start_unsafe_const(const void* addr) const {
   1.641 +  assert(_bottom <= addr && addr < _end,
   1.642 +         "addr must be covered by this Array");
   1.643 +  HeapWord* q = block_at_or_preceding(addr, true, _next_offset_index-1);
   1.644 +  HeapWord* n = q + _sp->block_size(q);
   1.645 +  return forward_to_block_containing_addr_const(q, n, addr);
   1.646 +}
   1.647 +
   1.648 +G1BlockOffsetArrayContigSpace::
   1.649 +G1BlockOffsetArrayContigSpace(G1BlockOffsetSharedArray* array,
   1.650 +                              MemRegion mr) :
   1.651 +  G1BlockOffsetArray(array, mr, true)
   1.652 +{
   1.653 +  _next_offset_threshold = NULL;
   1.654 +  _next_offset_index = 0;
   1.655 +}
   1.656 +
   1.657 +HeapWord* G1BlockOffsetArrayContigSpace::initialize_threshold() {
   1.658 +  assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
   1.659 +         "just checking");
   1.660 +  _next_offset_index = _array->index_for(_bottom);
   1.661 +  _next_offset_index++;
   1.662 +  _next_offset_threshold =
   1.663 +    _array->address_for_index(_next_offset_index);
   1.664 +  return _next_offset_threshold;
   1.665 +}
   1.666 +
   1.667 +void G1BlockOffsetArrayContigSpace::zero_bottom_entry() {
   1.668 +  assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
   1.669 +         "just checking");
   1.670 +  size_t bottom_index = _array->index_for(_bottom);
   1.671 +  assert(_array->address_for_index(bottom_index) == _bottom,
   1.672 +         "Precondition of call");
   1.673 +  _array->set_offset_array(bottom_index, 0);
   1.674 +}
   1.675 +
   1.676 +void
   1.677 +G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* new_top) {
   1.678 +  assert(new_top <= _end, "_end should have already been updated");
   1.679 +
   1.680 +  // The first BOT entry should have offset 0.
   1.681 +  zero_bottom_entry();
   1.682 +  initialize_threshold();
   1.683 +  alloc_block(_bottom, new_top);
   1.684 + }
   1.685 +
   1.686 +#ifndef PRODUCT
   1.687 +void
   1.688 +G1BlockOffsetArrayContigSpace::print_on(outputStream* out) {
   1.689 +  G1BlockOffsetArray::print_on(out);
   1.690 +  out->print_cr("  next offset threshold: "PTR_FORMAT, _next_offset_threshold);
   1.691 +  out->print_cr("  next offset index:     "SIZE_FORMAT, _next_offset_index);
   1.692 +}
   1.693 +#endif // !PRODUCT

mercurial