# HG changeset patch # User tonyp # Date 1301452576 14400 # Node ID 455328d90876c6e262da68821ebf44a15a58dfa1 # Parent 02f49b66361a1ad8b4721bc9c366d1be517a5b98 7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end Summary: What the synopsis says. Reviewed-by: jwilhelm, iveresov, johnc diff -r 02f49b66361a -r 455328d90876 src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Mon Mar 28 10:58:54 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Tue Mar 29 22:36:16 2011 -0400 @@ -3879,7 +3879,7 @@ if (r->is_empty()) { // We didn't actually allocate anything in it; let's just put // it back on the free list. - _free_list.add_as_tail(r); + _free_list.add_as_head(r); } else if (_retain_gc_alloc_region[ap] && !totally) { // retain it so that we can use it at the beginning of the next GC _retained_gc_alloc_regions[ap] = r; @@ -5013,7 +5013,7 @@ *pre_used += hr->used(); hr->hr_clear(par, true /* clear_space */); - free_list->add_as_tail(hr); + free_list->add_as_head(hr); } void G1CollectedHeap::free_humongous_region(HeapRegion* hr, @@ -5065,7 +5065,7 @@ } if (free_list != NULL && !free_list->is_empty()) { MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag); - _free_list.add_as_tail(free_list); + _free_list.add_as_head(free_list); } if (humongous_proxy_set != NULL && !humongous_proxy_set->is_empty()) { MutexLockerEx x(OldSets_lock, Mutex::_no_safepoint_check_flag); diff -r 02f49b66361a -r 455328d90876 src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Mon Mar 28 10:58:54 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Tue Mar 29 22:36:16 2011 -0400 @@ -1061,7 +1061,7 @@ } void append_secondary_free_list() { - _free_list.add_as_tail(&_secondary_free_list); + _free_list.add_as_head(&_secondary_free_list); } void append_secondary_free_list_if_not_empty_with_lock() { diff -r 02f49b66361a -r 455328d90876 src/share/vm/gc_implementation/g1/heapRegionSet.cpp --- a/src/share/vm/gc_implementation/g1/heapRegionSet.cpp Mon Mar 28 10:58:54 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/heapRegionSet.cpp Tue Mar 29 22:36:16 2011 -0400 @@ -261,6 +261,45 @@ msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, head(), tail()); } +void HeapRegionLinkedList::add_as_head(HeapRegionLinkedList* from_list) { + hrs_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(from_list); + + verify_optional(); + from_list->verify_optional(); + + if (from_list->is_empty()) return; + +#ifdef ASSERT + HeapRegionLinkedListIterator iter(from_list); + while (iter.more_available()) { + HeapRegion* hr = iter.get_next(); + // In set_containing_set() we check that we either set the value + // from NULL to non-NULL or vice versa to catch bugs. So, we have + // to NULL it first before setting it to the value. + hr->set_containing_set(NULL); + hr->set_containing_set(this); + } +#endif // ASSERT + + if (_head != NULL) { + assert(length() > 0 && _tail != NULL, hrs_ext_msg(this, "invariant")); + from_list->_tail->set_next(_head); + } else { + assert(length() == 0 && _head == NULL, hrs_ext_msg(this, "invariant")); + _tail = from_list->_tail; + } + _head = from_list->_head; + + _length += from_list->length(); + _region_num += from_list->region_num(); + _total_used_bytes += from_list->total_used_bytes(); + from_list->clear(); + + verify_optional(); + from_list->verify_optional(); +} + void HeapRegionLinkedList::add_as_tail(HeapRegionLinkedList* from_list) { hrs_assert_mt_safety_ok(this); hrs_assert_mt_safety_ok(from_list); diff -r 02f49b66361a -r 455328d90876 src/share/vm/gc_implementation/g1/heapRegionSet.hpp --- a/src/share/vm/gc_implementation/g1/heapRegionSet.hpp Mon Mar 28 10:58:54 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/heapRegionSet.hpp Tue Mar 29 22:36:16 2011 -0400 @@ -277,6 +277,10 @@ } public: + // 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); + // It adds hr to the list as the new tail. The region should not be // a member of another set. inline void add_as_tail(HeapRegion* hr); @@ -290,6 +294,11 @@ // 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); + + // 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); diff -r 02f49b66361a -r 455328d90876 src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp --- a/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp Mon Mar 28 10:58:54 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp Tue Mar 29 22:36:16 2011 -0400 @@ -110,6 +110,23 @@ //////////////////// HeapRegionLinkedList //////////////////// +inline void HeapRegionLinkedList::add_as_head(HeapRegion* hr) { + hrs_assert_mt_safety_ok(this); + assert((length() == 0 && _head == NULL && _tail == NULL) || + (length() > 0 && _head != NULL && _tail != NULL), + hrs_ext_msg(this, "invariant")); + // add_internal() will verify the region. + add_internal(hr); + + // Now link the region. + if (_head != NULL) { + hr->set_next(_head); + } else { + _tail = hr; + } + _head = hr; +} + inline void HeapRegionLinkedList::add_as_tail(HeapRegion* hr) { hrs_assert_mt_safety_ok(this); assert((length() == 0 && _head == NULL && _tail == NULL) ||