8332139: SymbolTableHash::Node allocations allocates twice the required memory
Reviewed-by: iwalulya, coleenp
This commit is contained in:
parent
ba67ad63ae
commit
2c1da6c6fa
@ -172,7 +172,7 @@ public:
|
|||||||
// Deleting permanent symbol should not occur very often (insert race condition),
|
// Deleting permanent symbol should not occur very often (insert race condition),
|
||||||
// so log it.
|
// so log it.
|
||||||
log_trace_symboltable_helper(&value, "Freeing permanent symbol");
|
log_trace_symboltable_helper(&value, "Freeing permanent symbol");
|
||||||
size_t alloc_size = _local_table->get_node_size() + value.byte_size() + value.effective_length();
|
size_t alloc_size = SymbolTableHash::get_dynamic_node_size(value.byte_size());
|
||||||
if (!SymbolTable::arena()->Afree(memory, alloc_size)) {
|
if (!SymbolTable::arena()->Afree(memory, alloc_size)) {
|
||||||
log_trace_symboltable_helper(&value, "Leaked permanent symbol");
|
log_trace_symboltable_helper(&value, "Leaked permanent symbol");
|
||||||
}
|
}
|
||||||
@ -182,7 +182,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static void* allocate_node_impl(size_t size, Value const& value) {
|
static void* allocate_node_impl(size_t size, Value const& value) {
|
||||||
size_t alloc_size = size + value.byte_size() + value.effective_length();
|
size_t alloc_size = SymbolTableHash::get_dynamic_node_size(value.byte_size());
|
||||||
#if INCLUDE_CDS
|
#if INCLUDE_CDS
|
||||||
if (CDSConfig::is_dumping_static_archive()) {
|
if (CDSConfig::is_dumping_static_archive()) {
|
||||||
MutexLocker ml(DumpRegion_lock, Mutex::_no_safepoint_check_flag);
|
MutexLocker ml(DumpRegion_lock, Mutex::_no_safepoint_check_flag);
|
||||||
|
@ -122,7 +122,7 @@ class Symbol : public MetaspaceObj {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int byte_size(int length) {
|
static int byte_size(int length) {
|
||||||
// minimum number of natural words needed to hold these bits (no non-heap version)
|
// minimum number of bytes needed to hold these bits (no non-heap version)
|
||||||
return (int)(sizeof(Symbol) + (length > 2 ? length - 2 : 0));
|
return (int)(sizeof(Symbol) + (length > 2 ? length - 2 : 0));
|
||||||
}
|
}
|
||||||
static int size(int length) {
|
static int size(int length) {
|
||||||
@ -146,8 +146,6 @@ class Symbol : public MetaspaceObj {
|
|||||||
|
|
||||||
int size() const { return size(utf8_length()); }
|
int size() const { return size(utf8_length()); }
|
||||||
int byte_size() const { return byte_size(utf8_length()); };
|
int byte_size() const { return byte_size(utf8_length()); };
|
||||||
// length without the _body
|
|
||||||
size_t effective_length() const { return (size_t)byte_size() - sizeof(Symbol); }
|
|
||||||
|
|
||||||
// Symbols should be stored in the read-only region of CDS archive.
|
// Symbols should be stored in the read-only region of CDS archive.
|
||||||
static bool is_read_only_by_default() { return true; }
|
static bool is_read_only_by_default() { return true; }
|
||||||
|
@ -91,6 +91,13 @@ class ConcurrentHashTable : public CHeapObj<F> {
|
|||||||
|
|
||||||
void print_on(outputStream* st) const {};
|
void print_on(outputStream* st) const {};
|
||||||
void print_value_on(outputStream* st) const {};
|
void print_value_on(outputStream* st) const {};
|
||||||
|
|
||||||
|
static bool is_dynamic_sized_value_compatible() {
|
||||||
|
// To support dynamically sized Value types, where part of the payload is
|
||||||
|
// allocated beyond the end of the object, it must be that the _value
|
||||||
|
// field ends where the Node object ends. (No end padding).
|
||||||
|
return offset_of(Node, _value) + sizeof(_value) == sizeof(Node);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Only constructed with placement new from an array allocated with MEMFLAGS
|
// Only constructed with placement new from an array allocated with MEMFLAGS
|
||||||
@ -419,6 +426,7 @@ class ConcurrentHashTable : public CHeapObj<F> {
|
|||||||
|
|
||||||
size_t get_size_log2(Thread* thread);
|
size_t get_size_log2(Thread* thread);
|
||||||
static size_t get_node_size() { return sizeof(Node); }
|
static size_t get_node_size() { return sizeof(Node); }
|
||||||
|
static size_t get_dynamic_node_size(size_t value_size);
|
||||||
bool is_max_size_reached() { return _size_limit_reached; }
|
bool is_max_size_reached() { return _size_limit_reached; }
|
||||||
|
|
||||||
// This means no paused bucket resize operation is going to resume
|
// This means no paused bucket resize operation is going to resume
|
||||||
|
@ -1055,6 +1055,15 @@ inline size_t ConcurrentHashTable<CONFIG, F>::
|
|||||||
return _table->_log2_size;
|
return _table->_log2_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename CONFIG, MEMFLAGS F>
|
||||||
|
inline size_t ConcurrentHashTable<CONFIG, F>::
|
||||||
|
get_dynamic_node_size(size_t value_size)
|
||||||
|
{
|
||||||
|
assert(Node::is_dynamic_sized_value_compatible(), "VALUE must be compatible");
|
||||||
|
assert(value_size >= sizeof(VALUE), "must include the VALUE");
|
||||||
|
return sizeof(Node) - sizeof(VALUE) + value_size;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename CONFIG, MEMFLAGS F>
|
template <typename CONFIG, MEMFLAGS F>
|
||||||
inline bool ConcurrentHashTable<CONFIG, F>::
|
inline bool ConcurrentHashTable<CONFIG, F>::
|
||||||
shrink(Thread* thread, size_t size_limit_log2)
|
shrink(Thread* thread, size_t size_limit_log2)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user