mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8034079: G1: Refactor the HeapRegionSet hierarchy
Reviewed-by: tschatzl, pliden
This commit is contained in:
parent
1d21f8975b
commit
c88e3def4d
17 changed files with 447 additions and 923 deletions
|
@ -38,135 +38,108 @@ typedef FormatBuffer<HRS_ERR_MSG_BUFSZ> hrs_err_msg;
|
|||
#define HEAP_REGION_SET_FORCE_VERIFY defined(ASSERT)
|
||||
#endif // HEAP_REGION_SET_FORCE_VERIFY
|
||||
|
||||
//////////////////// HeapRegionSetBase ////////////////////
|
||||
class hrs_ext_msg;
|
||||
|
||||
class HRSMtSafeChecker : public CHeapObj<mtGC> {
|
||||
public:
|
||||
virtual void check() = 0;
|
||||
};
|
||||
|
||||
class MasterFreeRegionListMtSafeChecker : public HRSMtSafeChecker { public: void check(); };
|
||||
class SecondaryFreeRegionListMtSafeChecker : public HRSMtSafeChecker { public: void check(); };
|
||||
class HumongousRegionSetMtSafeChecker : public HRSMtSafeChecker { public: void check(); };
|
||||
class OldRegionSetMtSafeChecker : public HRSMtSafeChecker { public: void check(); };
|
||||
|
||||
class HeapRegionSetCount VALUE_OBJ_CLASS_SPEC {
|
||||
friend class VMStructs;
|
||||
uint _length;
|
||||
size_t _capacity;
|
||||
|
||||
public:
|
||||
HeapRegionSetCount() : _length(0), _capacity(0) { }
|
||||
|
||||
const uint length() const { return _length; }
|
||||
const size_t capacity() const { return _capacity; }
|
||||
|
||||
void increment(uint length_to_add, size_t capacity_to_add) {
|
||||
_length += length_to_add;
|
||||
_capacity += capacity_to_add;
|
||||
}
|
||||
|
||||
void decrement(const uint length_to_remove, const size_t capacity_to_remove) {
|
||||
_length -= length_to_remove;
|
||||
_capacity -= capacity_to_remove;
|
||||
}
|
||||
};
|
||||
|
||||
// Base class for all the classes that represent heap region sets. It
|
||||
// contains the basic attributes that each set needs to maintain
|
||||
// (e.g., length, region num, used bytes sum) plus any shared
|
||||
// functionality (e.g., verification).
|
||||
|
||||
class hrs_ext_msg;
|
||||
|
||||
typedef enum {
|
||||
HRSPhaseNone,
|
||||
HRSPhaseEvacuation,
|
||||
HRSPhaseCleanup,
|
||||
HRSPhaseFullGC
|
||||
} HRSPhase;
|
||||
|
||||
class HRSPhaseSetter;
|
||||
|
||||
class HeapRegionSetBase VALUE_OBJ_CLASS_SPEC {
|
||||
friend class hrs_ext_msg;
|
||||
friend class HRSPhaseSetter;
|
||||
friend class VMStructs;
|
||||
private:
|
||||
bool _is_humongous;
|
||||
bool _is_empty;
|
||||
HRSMtSafeChecker* _mt_safety_checker;
|
||||
|
||||
protected:
|
||||
static uint _unrealistically_long_length;
|
||||
|
||||
// The number of regions added to the set. If the set contains
|
||||
// only humongous regions, this reflects only 'starts humongous'
|
||||
// regions and does not include 'continues humongous' ones.
|
||||
uint _length;
|
||||
|
||||
// The total number of regions represented by the set. If the set
|
||||
// does not contain humongous regions, this should be the same as
|
||||
// _length. If the set contains only humongous regions, this will
|
||||
// include the 'continues humongous' regions.
|
||||
uint _region_num;
|
||||
|
||||
// We don't keep track of the total capacity explicitly, we instead
|
||||
// recalculate it based on _region_num and the heap region size.
|
||||
|
||||
// The sum of used bytes in the all the regions in the set.
|
||||
size_t _total_used_bytes;
|
||||
HeapRegionSetCount _count;
|
||||
|
||||
const char* _name;
|
||||
|
||||
bool _verify_in_progress;
|
||||
uint _calc_length;
|
||||
uint _calc_region_num;
|
||||
size_t _calc_total_capacity_bytes;
|
||||
size_t _calc_total_used_bytes;
|
||||
|
||||
// This is here so that it can be used in the subclasses to assert
|
||||
// something different depending on which phase the GC is in. This
|
||||
// can be particularly helpful in the check_mt_safety() methods.
|
||||
static HRSPhase _phase;
|
||||
|
||||
// Only used by HRSPhaseSetter.
|
||||
static void clear_phase();
|
||||
static void set_phase(HRSPhase phase);
|
||||
bool _verify_in_progress;
|
||||
|
||||
// verify_region() is used to ensure that the contents of a region
|
||||
// added to / removed from a set are consistent. Different sets
|
||||
// make different assumptions about the regions added to them. So
|
||||
// each set can override verify_region_extra(), which is called
|
||||
// from verify_region(), and do any extra verification it needs to
|
||||
// perform in that.
|
||||
virtual const char* verify_region_extra(HeapRegion* hr) { return NULL; }
|
||||
bool verify_region(HeapRegion* hr,
|
||||
HeapRegionSetBase* expected_containing_set);
|
||||
// added to / removed from a set are consistent.
|
||||
void verify_region(HeapRegion* hr) PRODUCT_RETURN;
|
||||
|
||||
// Indicates whether all regions in the set should be humongous or
|
||||
// not. Only used during verification.
|
||||
virtual bool regions_humongous() = 0;
|
||||
bool regions_humongous() { return _is_humongous; }
|
||||
|
||||
// Indicates whether all regions in the set should be empty or
|
||||
// not. Only used during verification.
|
||||
virtual bool regions_empty() = 0;
|
||||
bool regions_empty() { return _is_empty; }
|
||||
|
||||
// Subclasses can optionally override this to do MT safety protocol
|
||||
// checks. It is called in an assert from all methods that perform
|
||||
// updates on the set (and subclasses should also call it too).
|
||||
virtual bool check_mt_safety() { return true; }
|
||||
void check_mt_safety() {
|
||||
if (_mt_safety_checker != NULL) {
|
||||
_mt_safety_checker->check();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void fill_in_ext_msg_extra(hrs_ext_msg* msg) { }
|
||||
|
||||
HeapRegionSetBase(const char* name, bool humongous, bool empty, HRSMtSafeChecker* mt_safety_checker);
|
||||
|
||||
public:
|
||||
const char* name() { return _name; }
|
||||
|
||||
uint length() { return _count.length(); }
|
||||
|
||||
bool is_empty() { return _count.length() == 0; }
|
||||
|
||||
size_t total_capacity_bytes() {
|
||||
return _count.capacity();
|
||||
}
|
||||
|
||||
// It updates the fields of the set to reflect hr being added to
|
||||
// the set and tags the region appropriately.
|
||||
inline void add(HeapRegion* hr);
|
||||
|
||||
// It updates the fields of the set to reflect hr being removed
|
||||
// from the set and tags the region appropriately.
|
||||
inline void remove(HeapRegion* hr);
|
||||
|
||||
// fill_in_ext_msg() writes the the values of the set's attributes
|
||||
// in the custom err_msg (hrs_ext_msg). fill_in_ext_msg_extra()
|
||||
// allows subclasses to append further information.
|
||||
virtual void fill_in_ext_msg_extra(hrs_ext_msg* msg) { }
|
||||
void fill_in_ext_msg(hrs_ext_msg* msg, const char* message);
|
||||
|
||||
// It updates the fields of the set to reflect hr being added to
|
||||
// the set.
|
||||
inline void update_for_addition(HeapRegion* hr);
|
||||
|
||||
// It updates the fields of the set to reflect hr being added to
|
||||
// the set and tags the region appropriately.
|
||||
inline void add_internal(HeapRegion* hr);
|
||||
|
||||
// It updates the fields of the set to reflect hr being removed
|
||||
// from the set.
|
||||
inline void update_for_removal(HeapRegion* hr);
|
||||
|
||||
// It updates the fields of the set to reflect hr being removed
|
||||
// from the set and tags the region appropriately.
|
||||
inline void remove_internal(HeapRegion* hr);
|
||||
|
||||
// It clears all the fields of the sets. Note: it will not iterate
|
||||
// over the set and remove regions from it. It assumes that the
|
||||
// caller has already done so. It will literally just clear the fields.
|
||||
virtual void clear();
|
||||
|
||||
HeapRegionSetBase(const char* name);
|
||||
|
||||
public:
|
||||
static void set_unrealistically_long_length(uint len);
|
||||
|
||||
const char* name() { return _name; }
|
||||
|
||||
uint length() { return _length; }
|
||||
|
||||
bool is_empty() { return _length == 0; }
|
||||
|
||||
uint region_num() { return _region_num; }
|
||||
|
||||
size_t total_capacity_bytes() {
|
||||
return (size_t) region_num() << HeapRegion::LogOfHRGrainBytes;
|
||||
}
|
||||
|
||||
size_t total_used_bytes() { return _total_used_bytes; }
|
||||
|
||||
virtual void verify();
|
||||
void verify_start();
|
||||
void verify_next_region(HeapRegion* hr);
|
||||
|
@ -187,7 +160,6 @@ public:
|
|||
// assert/guarantee-specific message it also prints out the values of
|
||||
// the fields of the associated set. This can be very helpful in
|
||||
// diagnosing failures.
|
||||
|
||||
class hrs_ext_msg : public hrs_err_msg {
|
||||
public:
|
||||
hrs_ext_msg(HeapRegionSetBase* set, const char* message) : hrs_err_msg("") {
|
||||
|
@ -195,32 +167,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class HRSPhaseSetter {
|
||||
public:
|
||||
HRSPhaseSetter(HRSPhase phase) {
|
||||
HeapRegionSetBase::set_phase(phase);
|
||||
}
|
||||
~HRSPhaseSetter() {
|
||||
HeapRegionSetBase::clear_phase();
|
||||
}
|
||||
};
|
||||
|
||||
// These two macros are provided for convenience, to keep the uses of
|
||||
// these two asserts a bit more concise.
|
||||
|
||||
#define hrs_assert_mt_safety_ok(_set_) \
|
||||
do { \
|
||||
assert((_set_)->check_mt_safety(), hrs_ext_msg((_set_), "MT safety")); \
|
||||
} while (0)
|
||||
|
||||
#define hrs_assert_region_ok(_set_, _hr_, _expected_) \
|
||||
do { \
|
||||
assert((_set_)->verify_region((_hr_), (_expected_)), \
|
||||
hrs_ext_msg((_set_), "region verification")); \
|
||||
} while (0)
|
||||
|
||||
//////////////////// HeapRegionSet ////////////////////
|
||||
|
||||
#define hrs_assert_sets_match(_set1_, _set2_) \
|
||||
do { \
|
||||
assert(((_set1_)->regions_humongous() == \
|
||||
|
@ -236,63 +182,33 @@ public:
|
|||
// the same interface (namely, the HeapRegionSetBase API).
|
||||
|
||||
class HeapRegionSet : public HeapRegionSetBase {
|
||||
protected:
|
||||
virtual const char* verify_region_extra(HeapRegion* hr) {
|
||||
if (hr->next() != NULL) {
|
||||
return "next() should always be NULL as we do not link the regions";
|
||||
}
|
||||
|
||||
return HeapRegionSetBase::verify_region_extra(hr);
|
||||
}
|
||||
|
||||
HeapRegionSet(const char* name) : HeapRegionSetBase(name) {
|
||||
clear();
|
||||
}
|
||||
|
||||
public:
|
||||
// It adds hr to the set. The region should not be a member of
|
||||
// another set.
|
||||
inline void add(HeapRegion* hr);
|
||||
HeapRegionSet(const char* name, bool humongous, HRSMtSafeChecker* mt_safety_checker):
|
||||
HeapRegionSetBase(name, humongous, false /* empty */, mt_safety_checker) { }
|
||||
|
||||
// It removes hr from the set. The region should be a member of
|
||||
// this set.
|
||||
inline void remove(HeapRegion* hr);
|
||||
|
||||
// It removes a region from the set. Instead of updating the fields
|
||||
// of the set to reflect this removal, it accumulates the updates
|
||||
// in proxy_set. The idea is that proxy_set is thread-local to
|
||||
// avoid multiple threads updating the fields of the set
|
||||
// concurrently and having to synchronize. The method
|
||||
// update_from_proxy() will update the fields of the set from the
|
||||
// proxy_set.
|
||||
inline void remove_with_proxy(HeapRegion* hr, HeapRegionSet* proxy_set);
|
||||
|
||||
// After multiple calls to remove_with_proxy() the updates to the
|
||||
// fields of the set are accumulated in proxy_set. This call
|
||||
// updates the fields of the set from proxy_set.
|
||||
void update_from_proxy(HeapRegionSet* proxy_set);
|
||||
void bulk_remove(const HeapRegionSetCount& removed) {
|
||||
_count.decrement(removed.length(), removed.capacity());
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////// HeapRegionLinkedList ////////////////////
|
||||
|
||||
// A set that links all the regions added to it in a singly-linked
|
||||
// list. We should try to avoid doing operations that iterate over
|
||||
// such lists in performance critical paths. Typically we should
|
||||
// add / remove one region at a time or concatenate two lists. All
|
||||
// those operations are done in constant time.
|
||||
|
||||
class HeapRegionLinkedListIterator;
|
||||
class FreeRegionListIterator;
|
||||
|
||||
class HeapRegionLinkedList : public HeapRegionSetBase {
|
||||
friend class HeapRegionLinkedListIterator;
|
||||
class FreeRegionList : public HeapRegionSetBase {
|
||||
friend class FreeRegionListIterator;
|
||||
|
||||
private:
|
||||
HeapRegion* _head;
|
||||
HeapRegion* _tail;
|
||||
|
||||
// These are provided for use by the friend classes.
|
||||
HeapRegion* head() { return _head; }
|
||||
HeapRegion* tail() { return _tail; }
|
||||
static uint _unrealistically_long_length;
|
||||
|
||||
void add_as_head_or_tail(FreeRegionList* from_list, bool as_head);
|
||||
|
||||
protected:
|
||||
virtual void fill_in_ext_msg_extra(hrs_ext_msg* msg);
|
||||
|
@ -300,11 +216,19 @@ protected:
|
|||
// See the comment for HeapRegionSetBase::clear()
|
||||
virtual void clear();
|
||||
|
||||
HeapRegionLinkedList(const char* name) : HeapRegionSetBase(name) {
|
||||
public:
|
||||
FreeRegionList(const char* name, HRSMtSafeChecker* mt_safety_checker = NULL):
|
||||
HeapRegionSetBase(name, false /* humongous */, true /* empty */, mt_safety_checker) {
|
||||
clear();
|
||||
}
|
||||
|
||||
public:
|
||||
void verify_list();
|
||||
|
||||
HeapRegion* head() { return _head; }
|
||||
HeapRegion* tail() { return _tail; }
|
||||
|
||||
static void set_unrealistically_long_length(uint len);
|
||||
|
||||
// It adds hr to the list as the new head. The region should not be
|
||||
// a member of another set.
|
||||
inline void add_as_head(HeapRegion* hr);
|
||||
|
@ -323,12 +247,12 @@ public:
|
|||
// It moves the regions from from_list to this list and empties
|
||||
// from_list. The new regions will appear in the same order as they
|
||||
// were in from_list and be linked in the beginning of this list.
|
||||
void add_as_head(HeapRegionLinkedList* from_list);
|
||||
void add_as_head(FreeRegionList* from_list);
|
||||
|
||||
// It moves the regions from from_list to this list and empties
|
||||
// from_list. The new regions will appear in the same order as they
|
||||
// were in from_list and be linked in the end of this list.
|
||||
void add_as_tail(HeapRegionLinkedList* from_list);
|
||||
void add_as_tail(FreeRegionList* from_list);
|
||||
|
||||
// It empties the list by removing all regions from it.
|
||||
void remove_all();
|
||||
|
@ -346,14 +270,12 @@ public:
|
|||
virtual void print_on(outputStream* out, bool print_contents = false);
|
||||
};
|
||||
|
||||
//////////////////// HeapRegionLinkedListIterator ////////////////////
|
||||
|
||||
// Iterator class that provides a convenient way to iterate over the
|
||||
// regions of a HeapRegionLinkedList instance.
|
||||
|
||||
class HeapRegionLinkedListIterator : public StackObj {
|
||||
class FreeRegionListIterator : public StackObj {
|
||||
private:
|
||||
HeapRegionLinkedList* _list;
|
||||
FreeRegionList* _list;
|
||||
HeapRegion* _curr;
|
||||
|
||||
public:
|
||||
|
@ -369,12 +291,12 @@ public:
|
|||
// do the "cycle" check.
|
||||
|
||||
HeapRegion* hr = _curr;
|
||||
assert(_list->verify_region(hr, _list), "region verification");
|
||||
_list->verify_region(hr);
|
||||
_curr = hr->next();
|
||||
return hr;
|
||||
}
|
||||
|
||||
HeapRegionLinkedListIterator(HeapRegionLinkedList* list)
|
||||
FreeRegionListIterator(FreeRegionList* list)
|
||||
: _curr(NULL), _list(list) {
|
||||
_curr = list->head();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue