// Adjust BOT to show that a previously whole block has been split
// into two.
void G1BlockOffsetArray::split_block(HeapWord* blk, size_t blk_size,
                                     size_t left_blk_size) {
  // Verify that the BOT shows [blk, blk + blk_size) to be one block.
  verify_single_block(blk, blk_size);
  // Update the BOT to indicate that [blk + left_blk_size, blk + blk_size)
  // is one single block.
  mark_block(blk + left_blk_size, blk + blk_size);
}
//////////////////////////////////////////////////////////////////////////
// BlockOffsetArrayNonContigSpace inlines
//////////////////////////////////////////////////////////////////////////
inline void G1BlockOffsetArray::freed(HeapWord* blk_start, HeapWord* blk_end) {
  // Verify that the BOT shows [blk_start, blk_end) to be one block.
  verify_single_block(blk_start, blk_end);
  // adjust _unallocated_block upward or downward
  // as appropriate
  if (BlockOffsetArrayUseUnallocatedBlock) {
    assert(_unallocated_block <= _end,
           "Inconsistent value for _unallocated_block");
    if (blk_end >= _unallocated_block && blk_start <= _unallocated_block) {
      // CMS-specific note: a block abutting _unallocated_block to
      // its left is being freed, a new block is being added or
      // we are resetting following a compaction
      _unallocated_block = blk_start;
    }
  }
}
void BlockOffsetArrayNonContigSpace::verify_single_block(
  HeapWord* blk, size_t size) {
  verify_single_block(blk, blk + size);
}
// Adjust BOT to show that a previously whole block has been split
// into two.  We verify the BOT for the first part (prefix) and
// update the  BOT for the second part (suffix).
//      blk is the start of the block
//      blk_size is the size of the original block
//      left_blk_size is the size of the first part of the split
void BlockOffsetArrayNonContigSpace::split_block(HeapWord* blk,
                                                 size_t blk_size,
                                                 size_t left_blk_size) {
  // Verify that the BOT shows [blk, blk + blk_size) to be one block.
  verify_single_block(blk, blk_size);
  // Update the BOT to indicate that [blk + left_blk_size, blk + blk_size)
  // is one single block.
  assert(blk_size > 0, "Should be positive");
  assert(left_blk_size > 0, "Should be positive");
  assert(left_blk_size < blk_size, "Not a split");

  // Start addresses of prefix block and suffix block.
  HeapWord* pref_addr = blk;
  HeapWord* suff_addr = blk + left_blk_size;
  HeapWord* end_addr  = blk + blk_size;

  // Indices for starts of prefix block and suffix block.
  size_t pref_index = _array->index_for(pref_addr);
  if (_array->address_for_index(pref_index) != pref_addr) {
    // pref_addr does not begin pref_index
    pref_index++;
  }

  size_t suff_index = _array->index_for(suff_addr);
  if (_array->address_for_index(suff_index) != suff_addr) {
    // suff_addr does not begin suff_index
    suff_index++;
  }

  // Definition: A block B, denoted [B_start, B_end) __starts__
  //     a card C, denoted [C_start, C_end), where C_start and C_end
  //     are the heap addresses that card C covers, iff
  //     B_start <= C_start < B_end.
  //
  //     We say that a card C "is started by" a block B, iff
  //     B "starts" C.
  //
  //     Note that the cardinality of the set of cards {C}
  //     started by a block B can be 0, 1, or more.
  //
  // Below, pref_index and suff_index are, respectively, the
  // first (least) card indices that the prefix and suffix of
  // the split start; end_index is one more than the index of
  // the last (greatest) card that blk starts.
  size_t end_index  = _array->index_for(end_addr - 1) + 1;

  // Calculate the # cards that the prefix and suffix affect.
  size_t num_pref_cards = suff_index - pref_index;

  size_t num_suff_cards = end_index  - suff_index;
  // Change the cards that need changing
  if (num_suff_cards > 0) {
    HeapWord* boundary = _array->address_for_index(suff_index);
    // Set the offset card for suffix block
    _array->set_offset_array(suff_index, boundary, suff_addr, true /* reducing */);
    // Change any further cards that need changing in the suffix
    if (num_pref_cards > 0) {
      if (num_pref_cards >= num_suff_cards) {
        // Unilaterally fix all of the suffix cards: closed card
        // index interval in args below.
        set_remainder_to_point_to_start_incl(suff_index + 1, end_index - 1, true /* reducing */);
      } else {
        // Unilaterally fix the first (num_pref_cards - 1) following
        // the "offset card" in the suffix block.
        set_remainder_to_point_to_start_incl(suff_index + 1,
          suff_index + num_pref_cards - 1, true /* reducing */);
        // Fix the appropriate cards in the remainder of the
        // suffix block -- these are the last num_pref_cards
        // cards in each power block of the "new" range plumbed
        // from suff_addr.
        bool more = true;
        uint i = 1;
        while (more && (i < N_powers)) {
          size_t back_by = power_to_cards_back(i);
          size_t right_index = suff_index + back_by - 1;
          size_t left_index  = right_index - num_pref_cards + 1;
          if (right_index >= end_index - 1) { // last iteration
            right_index = end_index - 1;
            more = false;
          }
          if (back_by > num_pref_cards) {
            // Fill in the remainder of this "power block", if it
            // is non-null.
            if (left_index <= right_index) {
              _array->set_offset_array(left_index, right_index,
                                     N_words + i - 1, true /* reducing */);
            } else {
              more = false; // we are done
            }
            i++;
            break;
          }
          i++;
        }
        while (more && (i < N_powers)) {
          size_t back_by = power_to_cards_back(i);
          size_t right_index = suff_index + back_by - 1;
          size_t left_index  = right_index - num_pref_cards + 1;
          if (right_index >= end_index - 1) { // last iteration
            right_index = end_index - 1;
            if (left_index > right_index) {
              break;
            }
            more  = false;
          }
          assert(left_index <= right_index, "Error");
          _array->set_offset_array(left_index, right_index, N_words + i - 1, true /* reducing */);
          i++;
        }
      }
    } // else no more cards to fix in suffix
  } // else nothing needs to be done
  // Verify that we did the right thing
  verify_single_block(pref_addr, left_blk_size);
  verify_single_block(suff_addr, blk_size - left_blk_size);
}