8384960: Convert MallocSiteTable to use Atomic<T>

Reviewed-by: stefank, cnorrbin, coleenp, dsimms
This commit is contained in:
Johan Sjölen 2026-05-22 10:53:04 +00:00
parent f1caad39e9
commit ca81806254
2 changed files with 29 additions and 23 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2026, 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,7 +29,7 @@
#include "utilities/permitForbiddenFunctions.hpp"
// Malloc site hashtable buckets
MallocSiteHashtableEntry** MallocSiteTable::_table = nullptr;
Atomic<MallocSiteHashtableEntry*>* MallocSiteTable::_table = nullptr;
const NativeCallStack* MallocSiteTable::_hash_entry_allocation_stack = nullptr;
const MallocSiteHashtableEntry* MallocSiteTable::_hash_entry_allocation_site = nullptr;
@ -42,10 +42,13 @@ const MallocSiteHashtableEntry* MallocSiteTable::_hash_entry_allocation_site = n
* time, it is in single-threaded mode from JVM perspective.
*/
bool MallocSiteTable::initialize() {
_table = (MallocSiteHashtableEntry**)permit_forbidden_function::calloc(table_size, sizeof(MallocSiteHashtableEntry*));
_table = (Atomic<MallocSiteHashtableEntry*>*)permit_forbidden_function::malloc(table_size * sizeof(Atomic<MallocSiteHashtableEntry*>));
if (_table == nullptr) {
return false;
}
for (int i = 0; i < table_size; i++) {
new (&_table[i]) Atomic<MallocSiteHashtableEntry*>(nullptr);
}
// Fake the call stack for hashtable entry allocation
assert(NMT_TrackingStackDepth > 1, "At least one tracking stack");
@ -78,7 +81,7 @@ bool MallocSiteTable::initialize() {
// Add the allocation site to hashtable.
int index = hash_to_index(entry.hash());
_table[index] = const_cast<MallocSiteHashtableEntry*>(&entry);
_table[index].store_relaxed(const_cast<MallocSiteHashtableEntry*>(&entry));
return true;
}
@ -88,12 +91,12 @@ bool MallocSiteTable::initialize() {
bool MallocSiteTable::walk(MallocSiteWalker* walker) {
MallocSiteHashtableEntry* head;
for (int index = 0; index < table_size; index ++) {
head = _table[index];
head = _table[index].load_relaxed();
while (head != nullptr) {
if (!walker->do_malloc_site(head->peek())) {
return false;
}
head = (MallocSiteHashtableEntry*)head->next();
head = head->next();
}
}
return true;
@ -117,13 +120,13 @@ MallocSite* MallocSiteTable::lookup_or_add(const NativeCallStack& key, uint32_t*
*marker = 0;
// First entry for this hash bucket
if (_table[index] == nullptr) {
if (_table[index].load_relaxed() == nullptr) {
MallocSiteHashtableEntry* entry = new_entry(key, mem_tag);
// OOM check
if (entry == nullptr) return nullptr;
// swap in the head
if (AtomicAccess::replace_if_null(&_table[index], entry)) {
if (_table[index].compare_set(nullptr, entry)) {
*marker = build_marker(index, 0);
return entry->data();
}
@ -132,7 +135,7 @@ MallocSite* MallocSiteTable::lookup_or_add(const NativeCallStack& key, uint32_t*
}
unsigned pos_idx = 0;
MallocSiteHashtableEntry* head = _table[index];
MallocSiteHashtableEntry* head = _table[index].load_relaxed();
while (head != nullptr && pos_idx < MAX_BUCKET_LENGTH) {
if (head->hash() == hash) {
MallocSite* site = head->data();
@ -154,7 +157,7 @@ MallocSite* MallocSiteTable::lookup_or_add(const NativeCallStack& key, uint32_t*
// contended, other thread won
delete entry;
}
head = (MallocSiteHashtableEntry*)head->next();
head = head->next();
pos_idx ++;
}
return nullptr;
@ -167,10 +170,10 @@ MallocSite* MallocSiteTable::malloc_site(uint32_t marker) {
return nullptr;
}
const uint16_t pos_idx = pos_idx_from_marker(marker);
MallocSiteHashtableEntry* head = _table[bucket_idx];
MallocSiteHashtableEntry* head = _table[bucket_idx].load_relaxed();
for (size_t index = 0;
index < pos_idx && head != nullptr;
index++, head = (MallocSiteHashtableEntry*)head->next()) {}
index++, head = head->next()) {}
if (head == nullptr) {
return nullptr;
}
@ -213,7 +216,7 @@ void MallocSiteTable::print_tuning_statistics(outputStream* st) {
for (int i = 0; i < table_size; i ++) {
int this_chain_length = 0;
const MallocSiteHashtableEntry* head = _table[i];
const MallocSiteHashtableEntry* head = _table[i].load_relaxed();
if (head == nullptr) {
unused_buckets ++;
}
@ -254,5 +257,5 @@ void MallocSiteTable::print_tuning_statistics(outputStream* st) {
}
bool MallocSiteHashtableEntry::atomic_insert(MallocSiteHashtableEntry* entry) {
return AtomicAccess::replace_if_null(&_next, entry);
return _next.compare_set(nullptr, entry);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2026, 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,7 +29,7 @@
#include "nmt/allocationSite.hpp"
#include "nmt/mallocTracker.hpp"
#include "nmt/nmtCommon.hpp"
#include "runtime/atomicAccess.hpp"
#include "runtime/atomic.hpp"
#include "utilities/macros.hpp"
#include "utilities/nativeCallStack.hpp"
@ -57,9 +57,9 @@ class MallocSite : public AllocationSite {
// Malloc site hashtable entry
class MallocSiteHashtableEntry : public CHeapObj<mtNMT> {
private:
MallocSite _malloc_site;
const unsigned int _hash;
MallocSiteHashtableEntry* volatile _next;
MallocSite _malloc_site;
const unsigned int _hash;
Atomic<MallocSiteHashtableEntry*> _next;
public:
@ -69,7 +69,10 @@ class MallocSiteHashtableEntry : public CHeapObj<mtNMT> {
}
inline const MallocSiteHashtableEntry* next() const {
return _next;
return _next.load_relaxed();
}
inline MallocSiteHashtableEntry* next() {
return _next.load_relaxed();
}
// Insert an entry atomically.
@ -193,9 +196,9 @@ class MallocSiteTable : AllStatic {
private:
// The callsite hashtable. It has to be a static table,
// since malloc call can come from C runtime linker.
static MallocSiteHashtableEntry** _table;
static const NativeCallStack* _hash_entry_allocation_stack;
static const MallocSiteHashtableEntry* _hash_entry_allocation_site;
static Atomic<MallocSiteHashtableEntry*>* _table;
static const NativeCallStack* _hash_entry_allocation_stack;
static const MallocSiteHashtableEntry* _hash_entry_allocation_site;
};
#endif // SHARE_NMT_MALLOCSITETABLE_HPP