# HG changeset patch # User ysr # Date 1317952607 25200 # Node ID b9390528617c84dfb71b6a92706ef3fc28b34c30 # Parent fd65bc7c09b66940fdb499cdbd7bc4c6ee5a37ff 7095236: G1: _markedRegions never contains NULL regions Summary: Removed the code for skipping over NULL regions in _markedRegions, replacing it with an assertion that a NULL region is never encountered; removed dead methods, remove() and remove_region(), and inlined a simplified addRegion() directly into fillCache(). Reviewed-by: brutisso, tonyp diff -r fd65bc7c09b6 -r b9390528617c src/share/vm/gc_implementation/g1/collectionSetChooser.cpp --- a/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp Thu Oct 06 13:28:09 2011 -0400 +++ b/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp Thu Oct 06 18:56:47 2011 -0700 @@ -118,30 +118,6 @@ } } -// this is a bit expensive... but we expect that it should not be called -// to often. -void CSetChooserCache::remove(HeapRegion *hr) { - assert(_occupancy > 0, "cache should not be empty"); - assert(hr->sort_index() < -1, "should already be in the cache"); - int index = get_index(hr->sort_index()); - assert(_cache[index] == hr, "index should be correct"); - int next_index = trim_index(index + 1); - int last_index = trim_index(_first + _occupancy - 1); - while (index != last_index) { - assert(_cache[next_index] != NULL, "should not be null"); - _cache[index] = _cache[next_index]; - _cache[index]->set_sort_index(get_sort_index(index)); - - index = next_index; - next_index = trim_index(next_index+1); - } - assert(index == last_index, "should have reached the last one"); - _cache[index] = NULL; - hr->set_sort_index(-1); - --_occupancy; - assert(verify(), "cache should be consistent"); -} - static inline int orderRegions(HeapRegion* hr1, HeapRegion* hr2) { if (hr1 == NULL) { if (hr2 == NULL) return 0; @@ -197,43 +173,34 @@ HeapRegion *prev = NULL; while (index < _numMarkedRegions) { HeapRegion *curr = _markedRegions.at(index++); - if (curr != NULL) { - int si = curr->sort_index(); - guarantee(!curr->is_young(), "should not be young!"); - guarantee(si > -1 && si == (index-1), "sort index invariant"); - if (prev != NULL) { - guarantee(orderRegions(prev, curr) != 1, "regions should be sorted"); - } - prev = curr; + guarantee(curr != NULL, "Regions in _markedRegions array cannot be NULL"); + int si = curr->sort_index(); + guarantee(!curr->is_young(), "should not be young!"); + guarantee(si > -1 && si == (index-1), "sort index invariant"); + if (prev != NULL) { + guarantee(orderRegions(prev, curr) != 1, "regions should be sorted"); } + prev = curr; } return _cache.verify(); } #endif -bool -CollectionSetChooser::addRegionToCache() { - assert(!_cache.is_full(), "cache should not be full"); - - HeapRegion *hr = NULL; - while (hr == NULL && _curMarkedIndex < _numMarkedRegions) { - hr = _markedRegions.at(_curMarkedIndex++); - } - if (hr == NULL) - return false; - assert(!hr->is_young(), "should not be young!"); - assert(hr->sort_index() == _curMarkedIndex-1, "sort_index invariant"); - _markedRegions.at_put(hr->sort_index(), NULL); - _cache.insert(hr); - assert(!_cache.is_empty(), "cache should not be empty"); - assert(verify(), "cache should be consistent"); - return false; -} - void CollectionSetChooser::fillCache() { - while (!_cache.is_full() && addRegionToCache()) { + while (!_cache.is_full() && (_curMarkedIndex < _numMarkedRegions)) { + HeapRegion* hr = _markedRegions.at(_curMarkedIndex); + assert(hr != NULL, + err_msg("Unexpected NULL hr in _markedRegions at index %d", + _curMarkedIndex)); + _curMarkedIndex += 1; + assert(!hr->is_young(), "should not be young!"); + assert(hr->sort_index() == _curMarkedIndex-1, "sort_index invariant"); + _markedRegions.at_put(hr->sort_index(), NULL); + _cache.insert(hr); + assert(!_cache.is_empty(), "cache should not be empty"); } + assert(verify(), "cache should be consistent"); } void @@ -334,20 +301,6 @@ clearMarkedHeapRegions(); } -void CollectionSetChooser::removeRegion(HeapRegion *hr) { - int si = hr->sort_index(); - assert(si == -1 || hr->is_marked(), "Sort index not valid."); - if (si > -1) { - assert(_markedRegions.at(si) == hr, "Sort index not valid." ); - _markedRegions.at_put(si, NULL); - } else if (si < -1) { - assert(_cache.region_in_cache(hr), "should be in the cache"); - _cache.remove(hr); - assert(hr->sort_index() == -1, "sort index invariant"); - } - hr->set_sort_index(-1); -} - // if time_remaining < 0.0, then this method should try to return // a region, whether it fits within the remaining time or not HeapRegion* diff -r fd65bc7c09b6 -r b9390528617c src/share/vm/gc_implementation/g1/collectionSetChooser.hpp --- a/src/share/vm/gc_implementation/g1/collectionSetChooser.hpp Thu Oct 06 13:28:09 2011 -0400 +++ b/src/share/vm/gc_implementation/g1/collectionSetChooser.hpp Thu Oct 06 18:56:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -29,6 +29,26 @@ #include "utilities/growableArray.hpp" // We need to sort heap regions by collection desirability. +// This sorting is currently done in two "stages". An initial sort is +// done following a cleanup pause as soon as all of the marked but +// non-empty regions have been identified and the completely empty +// ones reclaimed. +// This gives us a global sort on a GC efficiency metric +// based on predictive data available at that time. However, +// any of these regions that are collected will only be collected +// during a future GC pause, by which time it is possible that newer +// data might allow us to revise and/or refine the earlier +// pause predictions, leading to changes in expected gc efficiency +// order. To somewhat mitigate this obsolescence, more so in the +// case of regions towards the end of the list, which will be +// picked later, these pre-sorted regions from the _markedRegions +// array are not used as is, but a small prefix thereof is +// insertion-sorted again into a small cache, based on more +// recent remembered set information. Regions are then drawn +// from this cache to construct the collection set at each +// incremental GC. +// This scheme and/or its implementation may be subject to +// revision in the future. class CSetChooserCache VALUE_OBJ_CLASS_SPEC { private: @@ -37,8 +57,8 @@ } PrivateConstants; HeapRegion* _cache[CacheLength]; - int _occupancy; // number of region in cache - int _first; // "first" region in the cache + int _occupancy; // number of regions in cache + int _first; // (index of) "first" region in the cache // adding CacheLength to deal with negative values inline int trim_index(int index) { @@ -62,7 +82,6 @@ void clear(void); void insert(HeapRegion *hr); HeapRegion *remove_first(void); - void remove (HeapRegion *hr); inline HeapRegion *get_first(void) { return _cache[_first]; } @@ -102,7 +121,6 @@ void sortMarkedHeapRegions(); void fillCache(); - bool addRegionToCache(void); void addMarkedHeapRegion(HeapRegion *hr); // Must be called before calls to getParMarkedHeapRegionChunk. @@ -122,9 +140,6 @@ void updateAfterFullCollection(); - // Ensure that "hr" is not a member of the marked region array or the cache - void removeRegion(HeapRegion* hr); - bool unmarked_age_1_returned_as_new() { return _unmarked_age_1_returned_as_new; } // Returns true if the used portion of "_markedRegions" is properly