/*
 * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#include "gc/serial/serialBlockOffsetTable.inline.hpp"
#include "gc/shared/blockOffsetTable.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
#include "logging/log.hpp"
#include "memory/iterator.hpp"
#include "memory/memoryReserver.hpp"
#include "memory/universe.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/java.hpp"
#include "runtime/os.hpp"

// Return the number of slots needed for an offset array
// that covers mem_region_words words.
size_t SerialBlockOffsetTable::compute_size(size_t mem_region_words) {
  assert(mem_region_words % CardTable::card_size_in_words() == 0, "precondition");

  size_t number_of_slots = mem_region_words / CardTable::card_size_in_words();
  return os::align_up_vm_allocation_granularity(number_of_slots);
}

SerialBlockOffsetTable::SerialBlockOffsetTable(MemRegion reserved,
                                               size_t init_word_size):
  _reserved(reserved) {
  size_t size = compute_size(reserved.word_size());

  ReservedSpace rs = MemoryReserver::reserve(size, mtGC);

  if (!rs.is_reserved()) {
    vm_exit_during_initialization("Could not reserve enough space for heap offset array");
  }

  const bool initialized = _vs.initialize(rs, 0 /* committed_size */);

  assert(initialized, "Should never fail when commmitted_size is 0");

  _offset_base = (uint8_t*)(_vs.low_boundary() - (uintptr_t(reserved.start()) >> CardTable::card_shift()));
  resize(init_word_size);
  log_trace(gc, bot)("SerialBlockOffsetTable::SerialBlockOffsetTable: ");
  log_trace(gc, bot)("   rs.base(): " PTR_FORMAT " rs.size(): " SIZE_FORMAT_X_0 " rs end(): " PTR_FORMAT,
                     p2i(rs.base()), rs.size(), p2i(rs.base() + rs.size()));
  log_trace(gc, bot)("   _vs.low_boundary(): " PTR_FORMAT "  _vs.high_boundary(): " PTR_FORMAT,
                     p2i(_vs.low_boundary()), p2i(_vs.high_boundary()));
}

void SerialBlockOffsetTable::resize(size_t new_word_size) {
  assert(new_word_size <= _reserved.word_size(), "Resize larger than reserved");
  size_t new_size = compute_size(new_word_size);
  size_t old_size = _vs.committed_size();
  size_t delta;
  char* high = _vs.high();
  if (new_size > old_size) {
    delta = os::align_up_vm_page_size(new_size - old_size);
    assert(delta > 0, "just checking");
    if (!_vs.expand_by(delta)) {
      vm_exit_out_of_memory(delta, OOM_MMAP_ERROR, "offset table expansion");
    }
    assert(_vs.high() == high + delta, "invalid expansion");
  } else {
    delta = os::align_down_vm_page_size(old_size - new_size);
    if (delta == 0) return;
    _vs.shrink_by(delta);
    assert(_vs.high() == high - delta, "invalid expansion");
  }
}

static void fill_range(uint8_t* start, uint8_t* end, uint8_t value) {
  // + 1 for inclusive.
  memset(start, value, pointer_delta(end, start, sizeof(uint8_t)) + 1);
}

// Write the backskip value for each logarithmic region (array slots containing the same entry value).
//
//    offset
//    card             2nd                       3rd
//     | +- 1st        |                         |
//     v v             v                         v
//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+-+-+-
//    |x|0|0|0|0|0|0|0|1|1|1|1|1|1| ... |1|1|1|1|2|2|2|2|2|2| ...
//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+-+-+-
//    11              19                        75
//      12
//
//    offset card is the card that points to the start of an object
//      x - offset value of offset card
//    1st - start of first logarithmic region
//      0 corresponds to logarithmic value N_words + 0 and 2**(3 * 0) = 1
//    2nd - start of second logarithmic region
//      1 corresponds to logarithmic value N_words + 1 and 2**(3 * 1) = 8
//    3rd - start of third logarithmic region
//      2 corresponds to logarithmic value N_words + 2 and 2**(3 * 2) = 64
//
//    integer below the block offset entry is an example of
//    the index of the entry
//
//    Given an address,
//      Find the block offset table entry
//      Convert the entry to a back slide
//        (e.g., with today's, offset = 0x81 =>
//          back slip = 2**(3*(0x81 - N_words)) = 2**3) = 8
//      Move back N (e.g., 8) entries and repeat with the
//        value of the new entry
//
void SerialBlockOffsetTable::update_for_block_work(HeapWord* blk_start,
                                                   HeapWord* blk_end) {
  HeapWord* const cur_card_boundary = align_up_by_card_size(blk_start);
  uint8_t* const offset_card = entry_for_addr(cur_card_boundary);

  // The first card holds the actual offset.
  *offset_card = checked_cast<uint8_t>(pointer_delta(cur_card_boundary, blk_start));

  // Check if this block spans over other cards.
  uint8_t* end_card = entry_for_addr(blk_end - 1);
  assert(offset_card <= end_card, "inv");

  if (offset_card != end_card) {
    // Handling remaining cards.
    uint8_t* start_card_for_region = offset_card + 1;
    for (uint i = 0; i < BOTConstants::N_powers; i++) {
      // -1 so that the reach ends in this region and not at the start
      // of the next.
      uint8_t* reach = offset_card + BOTConstants::power_to_cards_back(i + 1) - 1;
      uint8_t value = checked_cast<uint8_t>(CardTable::card_size_in_words() + i);

      fill_range(start_card_for_region, MIN2(reach, end_card), value);
      start_card_for_region = reach + 1;

      if (reach >= end_card) {
        break;
      }
    }
    assert(start_card_for_region > end_card, "Sanity check");
  }

  DEBUG_ONLY(verify_for_block(blk_start, blk_end);)
}

HeapWord* SerialBlockOffsetTable::block_start_reaching_into_card(const void* addr) const {
  uint8_t* entry = entry_for_addr(addr);
  uint8_t offset = *entry;
  while (offset >= CardTable::card_size_in_words()) {
    // The excess of the offset from N_words indicates a power of Base
    // to go back by.
    size_t n_cards_back = BOTConstants::entry_to_cards_back(offset);
    entry -= n_cards_back;
    offset = *entry;
  }
  HeapWord* q = addr_for_entry(entry);
  return q - offset;
}

void SerialBlockOffsetTable::verify_for_block(HeapWord* blk_start, HeapWord* blk_end) const {
  assert(is_crossing_card_boundary(blk_start, blk_end), "precondition");

  uint8_t* start_card = entry_for_addr(align_up_by_card_size(blk_start));
  uint8_t* end_card = entry_for_addr(blk_end - 1);
  // Check cards in [start_card, end_card]
  assert(*start_card < CardTable::card_size_in_words(), "offset card");

  for (uint8_t* i = start_card + 1; i <= end_card; ++i) {
    const uint8_t* prev  = i - 1;
    const uint8_t* value = i;
    if (*prev != *value) {
      assert(*value >= *prev, "monotonic");
      size_t n_cards_back = BOTConstants::entry_to_cards_back(*value);
      assert(start_card == (i - n_cards_back), "inv");
    }
  }
}
