8034079: G1: Refactor the HeapRegionSet hierarchy

Reviewed-by: tschatzl, pliden
This commit is contained in:
Bengt Rutisson 2014-03-14 10:15:46 +01:00
parent 1d21f8975b
commit c88e3def4d
17 changed files with 447 additions and 923 deletions

View file

@ -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();
}