OpenJDK / amber / amber
changeset 60849:9623140d2685
8242038: G1: Lazily initialize RSHashTables
Reviewed-by: kbarrett, sjohanss, tschatzl
author | redestad |
---|---|
date | Thu, 09 Apr 2020 13:04:10 +0200 |
parents | 193e4179def8 |
children | 7992ff451fec |
files | src/hotspot/share/gc/g1/sparsePRT.cpp src/hotspot/share/gc/g1/sparsePRT.hpp |
diffstat | 2 files changed, 51 insertions(+), 20 deletions(-) [+] |
line wrap: on
line diff
--- a/src/hotspot/share/gc/g1/sparsePRT.cpp Wed Apr 08 22:58:42 2020 -0700 +++ b/src/hotspot/share/gc/g1/sparsePRT.cpp Thu Apr 09 13:04:10 2020 +0200 @@ -85,6 +85,21 @@ float RSHashTable::TableOccupancyFactor = 0.5f; +// The empty table can't hold any entries and is effectively immutable +// This means it can be used as an initial sentinel value +static int empty_buckets[] = { RSHashTable::NullEntry }; +RSHashTable RSHashTable::empty_table; + +RSHashTable::RSHashTable() : + _num_entries(0), + _capacity(0), + _capacity_mask(0), + _occupied_entries(0), + _entries(NULL), + _buckets(empty_buckets), + _free_region(0), + _free_list(NullEntry) { } + RSHashTable::RSHashTable(size_t capacity) : _num_entries((capacity * TableOccupancyFactor) + 1), _capacity(capacity), @@ -99,14 +114,19 @@ } RSHashTable::~RSHashTable() { - FREE_C_HEAP_ARRAY(SparsePRTEntry, _entries); - FREE_C_HEAP_ARRAY(int, _buckets); + // Nothing to free for empty RSHashTable + if (_buckets != empty_buckets) { + assert(_entries != NULL, "invariant"); + FREE_C_HEAP_ARRAY(SparsePRTEntry, _entries); + FREE_C_HEAP_ARRAY(int, _buckets); + } } void RSHashTable::clear() { + assert(_buckets != empty_buckets, "Shouldn't call this for the empty_table"); _occupied_entries = 0; - guarantee(_entries != NULL, "INV"); - guarantee(_buckets != NULL, "INV"); + guarantee(_entries != NULL, "invariant"); + guarantee(_buckets != NULL, "invariant"); guarantee(_capacity <= ((size_t)1 << (sizeof(int)*BitsPerByte-1)) - 1, "_capacity too large"); @@ -119,6 +139,7 @@ } SparsePRT::AddCardResult RSHashTable::add_card(RegionIdx_t region_ind, CardIdx_t card_index) { + assert(this != &empty_table, "can't add a card to the empty table"); SparsePRTEntry* e = entry_for_region_ind_create(region_ind); assert(e != NULL && e->r_ind() == region_ind, "Postcondition of call above."); @@ -207,7 +228,7 @@ bool RSHashTableBucketIter::has_next(SparsePRTEntry*& entry) { while (_bl_ind == RSHashTable::NullEntry) { - if (_tbl_ind == (int)_rsht->capacity() - 1) { + if (_tbl_ind + 1 >= _rsht->capacity()) { return false; } _tbl_ind++; @@ -231,12 +252,14 @@ // ---------------------------------------------------------------------- SparsePRT::SparsePRT() : - _table(new RSHashTable(InitialCapacity)) { + _table(&RSHashTable::empty_table) { } SparsePRT::~SparsePRT() { - delete _table; + if (_table != &RSHashTable::empty_table) { + delete _table; + } } @@ -262,23 +285,27 @@ } void SparsePRT::clear() { - // If the entry table is not at initial capacity, just create a new one. - if (_table->capacity() != InitialCapacity) { + // If the entry table not at initial capacity, just reset to the empty table. + if (_table->capacity() == InitialCapacity) { + _table->clear(); + } else if (_table != &RSHashTable::empty_table) { delete _table; - _table = new RSHashTable(InitialCapacity); - } else { - _table->clear(); + _table = &RSHashTable::empty_table; } } void SparsePRT::expand() { RSHashTable* last = _table; - _table = new RSHashTable(last->capacity() * 2); - for (size_t i = 0; i < last->num_entries(); i++) { - SparsePRTEntry* e = last->entry((int)i); - if (e->valid_entry()) { - _table->add_entry(e); + if (last != &RSHashTable::empty_table) { + _table = new RSHashTable(last->capacity() * 2); + for (size_t i = 0; i < last->num_entries(); i++) { + SparsePRTEntry* e = last->entry((int)i); + if (e->valid_entry()) { + _table->add_entry(e); + } } + delete last; + } else { + _table = new RSHashTable(InitialCapacity); } - delete last; }
--- a/src/hotspot/share/gc/g1/sparsePRT.hpp Wed Apr 08 22:58:42 2020 -0700 +++ b/src/hotspot/share/gc/g1/sparsePRT.hpp Thu Apr 09 13:04:10 2020 +0200 @@ -173,11 +173,15 @@ // deleted from any bucket lists. void free_entry(int fi); + // For the empty sentinel created at static initialization time + RSHashTable(); + public: RSHashTable(size_t capacity); ~RSHashTable(); static const int NullEntry = -1; + static RSHashTable empty_table; bool should_expand() const { return _occupied_entries == _num_entries; } @@ -215,8 +219,8 @@ // This is embedded in HRRS iterator. class RSHashTableBucketIter { - int _tbl_ind; // [-1, 0.._rsht->_capacity) - int _bl_ind; // [-1, 0.._rsht->_capacity) + uint _tbl_ind; // [0.._rsht->_capacity) + int _bl_ind; // [-1, 0.._rsht->_capacity) RSHashTable* _rsht;