/*
 * Copyright (c) 2023, 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.
 *
 */

#ifndef SHARE_GC_G1_G1CARDSETCONTAINERS_HPP
#define SHARE_GC_G1_G1CARDSETCONTAINERS_HPP

#include "gc/g1/g1CardSet.hpp"
#include "memory/allocation.hpp"
#include "runtime/atomic.hpp"
#include "utilities/bitMap.hpp"
#include "utilities/globalDefinitions.hpp"

// A helper class to encode a few card indexes within a ContainerPtr.
//
// The pointer value (either 32 or 64 bits) is split into two areas:
//
// - Header containing identifying tag and number of encoded cards.
// - Data area containing the card indexes themselves
//
// The header starts (from LSB) with the identifying tag (two bits,
// always 00), and three bits size. The size stores the number of
// valid card indexes after the header.
//
// The data area makes up the remainder of the word, with card indexes
// put one after another at increasing bit positions. The separate
// card indexes use just enough space (bits) to represent the whole
// range of cards needed for covering the whole range of values
// (typically in a region). There may be unused space at the top of
// the word.
//
// Example:
//
//   64 bit pointer size, with 8M-size regions (8M == 2^23)
// -> 2^14 (2^23 / 2^9) cards; each card represents 512 bytes in a region
// -> 14 bits per card; must have enough bits to hold the max card index
// -> may encode up to 4 cards into it, using 61 bits (5 bits header + 4 * 14)
//
// M                                                     L
// S                                                     S
// B                                                     B
// +------+         +---------------+--------------+-----+
// |unused|   ...   |  card_index1  | card_index0  |SSS00|
// +------+         +---------------+--------------+-----+
class G1CardSetInlinePtr : public StackObj {
  friend class G1CardSetContainersTest;

  using ContainerPtr = G1CardSet::ContainerPtr;

  ContainerPtr volatile * _value_addr;
  ContainerPtr _value;

  static const uint SizeFieldLen = 3;
  static const uint SizeFieldPos = 2;
  static const uint HeaderSize = G1CardSet::ContainerPtrHeaderSize + SizeFieldLen;

  static const uint BitsInValue = sizeof(ContainerPtr) * BitsPerByte;

  static const uintptr_t SizeFieldMask = (((uint)1 << SizeFieldLen) - 1) << SizeFieldPos;

  static uint8_t card_pos_for(uint const idx, uint const bits_per_card) {
    return (idx * bits_per_card + HeaderSize);
  }

  static ContainerPtr merge(ContainerPtr orig_value, uint card_in_region, uint idx, uint bits_per_card);

  static uint card_at(ContainerPtr value, uint const idx, uint const bits_per_card) {
    uint8_t card_pos = card_pos_for(idx, bits_per_card);
    uint result = ((uintptr_t)value >> card_pos) & (((uintptr_t)1 << bits_per_card) - 1);
    return result;
  }

  uint find(uint const card_idx, uint const bits_per_card, uint start_at, uint num_cards);

public:
  G1CardSetInlinePtr() : _value_addr(nullptr), _value((ContainerPtr)G1CardSet::ContainerInlinePtr) { }

  G1CardSetInlinePtr(ContainerPtr value) : _value_addr(nullptr), _value(value) {
    assert(G1CardSet::container_type(_value) == G1CardSet::ContainerInlinePtr, "Value " PTR_FORMAT " is not a valid G1CardSetInlinePtr.", p2i(_value));
  }

  G1CardSetInlinePtr(ContainerPtr volatile* value_addr, ContainerPtr value) : _value_addr(value_addr), _value(value) {
    assert(G1CardSet::container_type(_value) == G1CardSet::ContainerInlinePtr, "Value " PTR_FORMAT " is not a valid G1CardSetInlinePtr.", p2i(_value));
  }

  G1AddCardResult add(uint const card_idx, uint const bits_per_card, uint const max_cards_in_inline_ptr);

  bool contains(uint const card_idx, uint const bits_per_card);

  template <class CardVisitor>
  void iterate(CardVisitor& found, uint const bits_per_card);

  operator ContainerPtr () { return _value; }

  static uint max_cards_in_inline_ptr(uint bits_per_card) {
    return (BitsInValue - HeaderSize) / bits_per_card;
  }

  static uint num_cards_in(ContainerPtr value) {
    return ((uintptr_t)value & SizeFieldMask) >> SizeFieldPos;
  }
};


// Common base class for card set containers where the memory for the entries is
// managed on the (C-)heap. Depending on the current use, one of the two overlapping
// members are used:
//
// While such an object is assigned to a card set container, we utilize the
// reference count for memory management.
//
// In this case the object is one of three states:
// 1: Live: The object is visible to other threads, thus can
//    safely be accessed by other threads (_ref_count >= 3).
// 2: Dead: The object is visible to only a single thread and may be
//    safely reclaimed (_ref_count == 1).
// 3: Reclaimed: The object's memory has been reclaimed ((_ref_count & 0x1) == 0).
// To maintain these constraints, live objects should have ((_ref_count & 0x1) == 1),
// which requires that we increment the reference counts by 2 starting at _ref_count = 3.
//
// All but inline pointers are of this kind. For those, card entries are stored
// directly in the ContainerPtr of the ConcurrentHashTable node.
class G1CardSetContainer {
  uintptr_t _ref_count;
protected:
  ~G1CardSetContainer() = default;
public:
  G1CardSetContainer() : _ref_count(3) { }

  uintptr_t refcount() const { return Atomic::load_acquire(&_ref_count); }

  bool try_increment_refcount();

  // Decrement refcount potentially while racing increment, so we need
  // to check the value after attempting to decrement.
  uintptr_t decrement_refcount();

  // Log of largest card index that can be stored in any G1CardSetContainer
  static uint LogCardsPerRegionLimit;

  static uint cards_per_region_limit() { return 1u << LogCardsPerRegionLimit; }
};

class G1CardSetArray : public G1CardSetContainer {
public:
  typedef uint16_t EntryDataType;
  typedef uint EntryCountType;
  using ContainerPtr = G1CardSet::ContainerPtr;
private:
  EntryCountType _size;
  EntryCountType volatile _num_entries;
  EntryDataType _data[2];

  static const EntryCountType LockBitMask = (EntryCountType)1 << (sizeof(EntryCountType) * BitsPerByte - 1);
  static const EntryCountType EntryMask = LockBitMask - 1;

  class G1CardSetArrayLocker : public StackObj {
    EntryCountType volatile* _num_entries_addr;
    EntryCountType _local_num_entries;
  public:
    G1CardSetArrayLocker(EntryCountType volatile* value);

    EntryCountType num_entries() const { return _local_num_entries; }
    void inc_num_entries() {
      assert(((_local_num_entries + 1) & EntryMask) == (EntryCountType)(_local_num_entries + 1), "no overflow" );
      _local_num_entries++;
    }

    ~G1CardSetArrayLocker() {
      Atomic::release_store(_num_entries_addr, _local_num_entries);
    }
  };
public:
  G1CardSetArray(uint const card_in_region, EntryCountType num_cards);

  G1AddCardResult add(uint card_idx);

  bool contains(uint card_idx);

  template <class CardVisitor>
  void iterate(CardVisitor& found);

  size_t num_entries() const { return _num_entries & EntryMask; }

  static size_t header_size_in_bytes();

  static size_t size_in_bytes(size_t num_cards) {
    return header_size_in_bytes() + sizeof(EntryDataType) * num_cards;
  }
};

class G1CardSetBitMap : public G1CardSetContainer {
  size_t _num_bits_set;
  BitMap::bm_word_t _bits[1];

public:
  G1CardSetBitMap(uint const card_in_region, uint const size_in_bits);

  G1AddCardResult add(uint card_idx, size_t threshold, size_t size_in_bits);

  bool contains(uint card_idx, size_t size_in_bits) {
    BitMapView bm(_bits, size_in_bits);
    return bm.at(card_idx);
  }

  uint num_bits_set() const { return (uint)_num_bits_set; }

  template <class CardVisitor>
  void iterate(CardVisitor& found, size_t const size_in_bits, uint offset);

  uint next(uint const idx, size_t const size_in_bits) {
    BitMapView bm(_bits, size_in_bits);
    return static_cast<uint>(bm.find_first_set_bit(idx));
  }

  static size_t header_size_in_bytes();

  static size_t size_in_bytes(size_t size_in_bits) { return header_size_in_bytes() + BitMap::calc_size_in_words(size_in_bits) * BytesPerWord; }
};

class G1CardSetHowl : public G1CardSetContainer {
public:
  typedef uint EntryCountType;
  using ContainerPtr = G1CardSet::ContainerPtr;
  EntryCountType volatile _num_entries;
private:
  ContainerPtr _buckets[2];
  // Do not add class member variables beyond this point

  // Iterates over the given ContainerPtr with at index in this Howl card set,
  // applying a CardOrRangeVisitor on it.
  template <class CardOrRangeVisitor>
  void iterate_cardset(ContainerPtr const container, uint index, CardOrRangeVisitor& found, G1CardSetConfiguration* config);

public:
  G1CardSetHowl(EntryCountType card_in_region, G1CardSetConfiguration* config);

  ContainerPtr* get_container_addr(EntryCountType index) {
    return &_buckets[index];
  }

  bool contains(uint card_idx, G1CardSetConfiguration* config);

  // Iterates over all ContainerPtrs in this Howl card set, applying a CardOrRangeVisitor
  // on it.
  template <class CardOrRangeVisitor>
  void iterate(CardOrRangeVisitor& found, G1CardSetConfiguration* config);

  // Iterates over all ContainerPtrs in this Howl card set. Calls
  //
  //   void operator ()(ContainerPtr* card_set_addr);
  //
  // on all of them.
  template <class ContainerPtrVisitor>
  void iterate(ContainerPtrVisitor& found, uint num_card_sets);

  static EntryCountType num_buckets(size_t size_in_bits, size_t num_cards_in_array, size_t max_buckets);

  static EntryCountType bitmap_size(size_t size_in_bits, uint num_buckets) {
    EntryCountType num_cards = (EntryCountType)size_in_bits / num_buckets;
    return round_up_power_of_2(num_cards);
  }

  static size_t header_size_in_bytes();

  static size_t size_in_bytes(size_t num_arrays) {
    return header_size_in_bytes() + sizeof(ContainerPtr) * num_arrays;
  }
};

#endif // SHARE_GC_G1_G1CARDSETCONTAINERS_HPP
