blob: 80f4d0d670cdbffbe338a223775853f38593e2f2 [file] [log] [blame]
/*
* 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 */