diff --git a/src/hotspot/share/nmt/mallocSiteTable.cpp b/src/hotspot/share/nmt/mallocSiteTable.cpp index 0150a25cae3..0b8dc8e5fa0 100644 --- a/src/hotspot/share/nmt/mallocSiteTable.cpp +++ b/src/hotspot/share/nmt/mallocSiteTable.cpp @@ -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* 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*)permit_forbidden_function::malloc(table_size * sizeof(Atomic)); if (_table == nullptr) { return false; } + for (int i = 0; i < table_size; i++) { + new (&_table[i]) Atomic(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(&entry); + _table[index].store_relaxed(const_cast(&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); } diff --git a/src/hotspot/share/nmt/mallocSiteTable.hpp b/src/hotspot/share/nmt/mallocSiteTable.hpp index e4adff9cc50..d78e6ebba6e 100644 --- a/src/hotspot/share/nmt/mallocSiteTable.hpp +++ b/src/hotspot/share/nmt/mallocSiteTable.hpp @@ -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 { private: - MallocSite _malloc_site; - const unsigned int _hash; - MallocSiteHashtableEntry* volatile _next; + MallocSite _malloc_site; + const unsigned int _hash; + Atomic _next; public: @@ -69,7 +69,10 @@ class MallocSiteHashtableEntry : public CHeapObj { } 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* _table; + static const NativeCallStack* _hash_entry_allocation_stack; + static const MallocSiteHashtableEntry* _hash_entry_allocation_site; }; #endif // SHARE_NMT_MALLOCSITETABLE_HPP