/*
 * Copyright (c) 2019, 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_G1COLLECTIONSETCANDIDATES_HPP
#define SHARE_GC_G1_G1COLLECTIONSETCANDIDATES_HPP

#include "gc/g1/g1CollectionSetCandidates.hpp"
#include "gc/shared/workerThread.hpp"
#include "memory/allocation.hpp"
#include "runtime/globals.hpp"
#include "utilities/bitMap.hpp"
#include "utilities/growableArray.hpp"

class G1CollectionCandidateList;
class G1CollectionSetCandidates;
class HeapRegion;
class HeapRegionClosure;

using G1CollectionCandidateRegionListIterator = GrowableArrayIterator<HeapRegion*>;

// A set of HeapRegion*, a thin wrapper around GrowableArray.
class G1CollectionCandidateRegionList {
  GrowableArray<HeapRegion*> _regions;

public:
  G1CollectionCandidateRegionList();

  // Append a HeapRegion to the end of this list. The region must not be in the list
  // already.
  void append(HeapRegion* r);
  // Remove the given list of HeapRegion* from this list. The given list must be a prefix
  // of this list.
  void remove_prefix(G1CollectionCandidateRegionList* list);

  // Empty contents of the list.
  void clear();

  HeapRegion* at(uint index);

  uint length() const { return (uint)_regions.length(); }

  G1CollectionCandidateRegionListIterator begin() const { return _regions.begin(); }
  G1CollectionCandidateRegionListIterator end() const { return _regions.end(); }
};

class G1CollectionCandidateListIterator : public StackObj {
  G1CollectionCandidateList* _which;
  uint _position;

public:
  G1CollectionCandidateListIterator(G1CollectionCandidateList* which, uint position);

  G1CollectionCandidateListIterator& operator++();
  HeapRegion* operator*();

  bool operator==(const G1CollectionCandidateListIterator& rhs);
  bool operator!=(const G1CollectionCandidateListIterator& rhs);
};

// List of collection set candidates (regions with their efficiency) ordered by
// decreasing gc efficiency.
class G1CollectionCandidateList : public CHeapObj<mtGC> {
  friend class G1CollectionCandidateListIterator;

public:
  struct CandidateInfo {
    HeapRegion* _r;
    double _gc_efficiency;

    CandidateInfo() : CandidateInfo(nullptr, 0.0) { }
    CandidateInfo(HeapRegion* r, double gc_efficiency) : _r(r), _gc_efficiency(gc_efficiency) { }
  };

private:
  GrowableArray<CandidateInfo> _candidates;

public:
  G1CollectionCandidateList();

  // Put the given set of candidates into this list, preserving the efficiency ordering.
  void set(CandidateInfo* candidate_infos, uint num_infos);
  // Removes any HeapRegions stored in this list also in the other list. The other
  // list may only contain regions in this list, sorted by gc efficiency. It need
  // not be a prefix of this list. Returns the number of regions removed.
  // E.g. if this list is "A B G H", the other list may be "A G H", but not "F" (not in
  // this list) or "A H G" (wrong order).
  void remove(G1CollectionCandidateRegionList* other);

  void clear();

  CandidateInfo& at(uint position) { return _candidates.at(position); }

  uint length() const { return (uint)_candidates.length(); }

  void verify() PRODUCT_RETURN;

  // Comparison function to order regions in decreasing GC efficiency order. This
  // will cause regions with a lot of live objects and large remembered sets to end
  // up at the end of the list.
  static int compare(CandidateInfo* ci1, CandidateInfo* ci2);

  G1CollectionCandidateListIterator begin() {
    return G1CollectionCandidateListIterator(this, 0);
  }

  G1CollectionCandidateListIterator end() {
    return G1CollectionCandidateListIterator(this, length());
  }
};

// Iterator for G1CollectionSetCandidates.
class G1CollectionSetCandidatesIterator : public StackObj {
  G1CollectionSetCandidates* _which;
  uint _marking_position;

public:
  G1CollectionSetCandidatesIterator(G1CollectionSetCandidates* which, uint marking_position);

  G1CollectionSetCandidatesIterator& operator++();
  HeapRegion* operator*();

  bool operator==(const G1CollectionSetCandidatesIterator& rhs);
  bool operator!=(const G1CollectionSetCandidatesIterator& rhs);
};

// Tracks all collection set candidates, i.e. regions that could/should be evacuated soon.
//
// These candidate regions are tracked in a list of regions, sorted by decreasing
// "gc efficiency".
//
// Currently there is only one type of such regions:
//
// * marking_regions: the set of regions selected by concurrent marking to be
//                    evacuated to keep overall heap occupancy stable.
//                    They are guaranteed to be evacuated and cleared out during
//                    the mixed phase.
//
class G1CollectionSetCandidates : public CHeapObj<mtGC> {
  friend class G1CollectionSetCandidatesIterator;

  enum class CandidateOrigin : uint8_t {
    Invalid,
    Marking,                   // This region has been determined as candidate by concurrent marking.
    Verify                     // Special value for verification.
  };

  G1CollectionCandidateList _marking_regions;

  CandidateOrigin* _contains_map;
  uint _max_regions;

  // The number of regions from the last merge of candidates from the marking.
  uint _last_marking_candidates_length;

  bool is_from_marking(HeapRegion* r) const;

public:
  G1CollectionSetCandidates();
  ~G1CollectionSetCandidates();

  G1CollectionCandidateList& marking_regions() { return _marking_regions; }

  void initialize(uint max_regions);

  void clear();

  // Merge collection set candidates from marking into the current marking list
  // (which needs to be empty).
  void set_candidates_from_marking(G1CollectionCandidateList::CandidateInfo* candidate_infos,
                                   uint num_infos);
  // The most recent length of the list that had been merged last via
  // set_candidates_from_marking(). Used for calculating minimum collection set
  // regions.
  uint last_marking_candidates_length() const { return _last_marking_candidates_length; }

  // Remove the given regions from the candidates. All given regions must be part
  // of the candidates.
  void remove(G1CollectionCandidateRegionList* other);

  bool contains(const HeapRegion* r) const;

  const char* get_short_type_str(const HeapRegion* r) const;

  bool is_empty() const;
  bool has_more_marking_candidates() const;

  uint marking_regions_length() const { return _marking_regions.length(); }

private:
  void verify_helper(G1CollectionCandidateList* list, uint& from_marking, CandidateOrigin* verify_map) PRODUCT_RETURN;

public:
  void verify() PRODUCT_RETURN;

  uint length() const { return marking_regions_length(); }

  // Iteration
  G1CollectionSetCandidatesIterator begin() {
    return G1CollectionSetCandidatesIterator(this, 0);
  }

  G1CollectionSetCandidatesIterator end() {
    return G1CollectionSetCandidatesIterator(this, marking_regions_length());
  }
};

#endif /* SHARE_GC_G1_G1COLLECTIONSETCANDIDATES_HPP */

