Skip to content
Permalink
Browse files

8242038: G1: Lazily initialize RSHashTables

Reviewed-by: kbarrett, sjohanss, tschatzl
  • Loading branch information
cl4es committed Apr 9, 2020
1 parent 7c35140 commit cdfe841d3d2a61dd518f8edba722e642077fe504
Showing with 51 additions and 20 deletions.
  1. +45 −18 src/hotspot/share/gc/g1/sparsePRT.cpp
  2. +6 −2 src/hotspot/share/gc/g1/sparsePRT.hpp
@@ -85,6 +85,21 @@ void SparsePRTEntry::copy_cards(SparsePRTEntry* e) const {

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(size_t capacity) :
}

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 @@ void RSHashTable::clear() {
}

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 @@ void RSHashTable::add_entry(SparsePRTEntry* e) {

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 @@ size_t RSHashTable::mem_size() const {
// ----------------------------------------------------------------------

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 @@ bool SparsePRT::delete_entry(RegionIdx_t region_id) {
}

void SparsePRT::clear() {
// If the entry table is not at initial capacity, just create a new one.
if (_table->capacity() != InitialCapacity) {
delete _table;
_table = new RSHashTable(InitialCapacity);
} else {
// 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 = &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;
}
@@ -173,11 +173,15 @@ class RSHashTable : public CHeapObj<mtGC> {
// 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 @@ class RSHashTable : public CHeapObj<mtGC> {

// 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;

0 comments on commit cdfe841

Please sign in to comment.