Skip to content
Permalink
Browse files

8234328: VectorSet::clear can cause fragmentation

Reviewed-by: neliasso
  • Loading branch information
cl4es committed Dec 12, 2019
1 parent 5ca3e63 commit 40bbdf472c74c466393b49f52b59e78710f25c77
Showing with 23 additions and 33 deletions.
  1. +9 −15 src/hotspot/share/libadt/vectset.cpp
  2. +14 −18 src/hotspot/share/libadt/vectset.hpp
@@ -31,17 +31,20 @@

VectorSet::VectorSet(Arena *arena) : _size(2),
_data(NEW_ARENA_ARRAY(arena, uint32_t, 2)),
_data_size(2),
_set_arena(arena) {
_data[0] = 0;
_data[1] = 0;
}

// Expand the existing set to a bigger size
void VectorSet::grow(uint new_size) {
new_size = (new_size + bit_mask) >> word_bits;
assert(new_size > 0, "sanity");
uint x = next_power_of_2(new_size);
_data = REALLOC_ARENA_ARRAY(_set_arena, uint32_t, _data, _size, x);
void VectorSet::grow(uint new_word_capacity) {
assert(new_word_capacity < (1U << 30), "");
uint x = next_power_of_2(new_word_capacity);
if (x > _data_size) {
_data = REALLOC_ARENA_ARRAY(_set_arena, uint32_t, _data, _size, x);
_data_size = x;
}
Copy::zero_to_bytes(_data + _size, (x - _size) * sizeof(uint32_t));
_size = x;
}
@@ -51,20 +54,11 @@ void VectorSet::insert(uint elem) {
uint32_t word = elem >> word_bits;
uint32_t mask = 1U << (elem & bit_mask);
if (word >= _size) {
grow(elem + 1);
grow(word);
}
_data[word] |= mask;
}

// Resets the storage
void VectorSet::reset_memory() {
assert(_size >= 2, "_size can never be less than 2");
_data = REALLOC_ARENA_ARRAY(_set_arena, uint32_t, _data, _size, 2);
_size = 2;
_data[0] = 0;
_data[1] = 0;
}

// Return true if the set is empty
bool VectorSet::is_empty() const {
for (uint32_t i = 0; i < _size; i++) {
@@ -40,28 +40,26 @@ class VectorSet : public ResourceObj {
static const uint word_bits = 5;
static const uint bit_mask = 31;

uint _size; // Size of data in 32-bit words
uint32_t* _data; // The data, bit packed
// Used 32-bit words
uint _size;
uint32_t* _data;
// Allocated words
uint _data_size;
Arena* _set_arena;

void grow(uint newsize); // Grow vector to required bitsize
void reset_memory();
// Grow vector to required word capacity
void grow(uint new_word_capacity);
public:
VectorSet(Arena *arena);
~VectorSet() {}

void insert(uint elem);
bool is_empty() const;
void reset() {
Copy::zero_to_bytes(_data, _size * sizeof(uint32_t));
_size = 0;
}
void clear() {
// Reclaim storage if huge
if (_size > 100) {
reset_memory();
} else {
reset();
}
reset();
}

// Fast inlined "test and set". Replaces the idiom:
@@ -73,9 +71,8 @@ class VectorSet : public ResourceObj {
bool test_set(uint elem) {
uint32_t word = elem >> word_bits;
if (word >= _size) {
// Then grow; set; return 0;
this->insert(elem);
return false;
// Then grow
grow(word);
}
uint32_t mask = 1U << (elem & bit_mask);
uint32_t data = _data[word];
@@ -106,11 +103,10 @@ class VectorSet : public ResourceObj {
void set(uint elem) {
uint32_t word = elem >> word_bits;
if (word >= _size) {
this->insert(elem);
} else {
uint32_t mask = 1U << (elem & bit_mask);
_data[word] |= mask;
grow(word);
}
uint32_t mask = 1U << (elem & bit_mask);
_data[word] |= mask;
}
};

0 comments on commit 40bbdf4

Please sign in to comment.
You can’t perform that action at this time.