8319439: Move BufferNode from PtrQueue files to new files

Reviewed-by: tschatzl, iwalulya
This commit is contained in:
Kim Barrett 2023-11-15 01:09:09 +00:00
parent d5abe49670
commit 1e76ba0cd0
17 changed files with 231 additions and 160 deletions

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2023, 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,6 +29,7 @@
#include "gc/g1/g1SATBMarkQueueSet.hpp"
#include "gc/shared/cardTable.hpp"
#include "gc/shared/cardTableBarrierSet.hpp"
#include "gc/shared/bufferNode.hpp"
class G1CardTable;

@ -25,8 +25,8 @@
#ifndef SHARE_GC_G1_G1CARDTABLEENTRYCLOSURE_HPP
#define SHARE_GC_G1_G1CARDTABLEENTRYCLOSURE_HPP
#include "gc/shared/bufferNode.hpp"
#include "gc/shared/cardTable.hpp"
#include "gc/shared/ptrQueue.hpp"
#include "memory/allocation.hpp"
// A closure class for processing card table entries. Note that we don't

@ -34,6 +34,7 @@
#include "gc/g1/g1RemSet.hpp"
#include "gc/g1/g1ThreadLocalData.hpp"
#include "gc/g1/heapRegionRemSet.inline.hpp"
#include "gc/shared/bufferNode.hpp"
#include "gc/shared/bufferNodeList.hpp"
#include "gc/shared/suspendibleThreadSet.hpp"
#include "memory/iterator.hpp"

@ -28,6 +28,7 @@
#include "gc/g1/g1FreeIdSet.hpp"
#include "gc/g1/g1CardTable.hpp"
#include "gc/g1/g1ConcurrentRefineStats.hpp"
#include "gc/shared/bufferNode.hpp"
#include "gc/shared/bufferNodeList.hpp"
#include "gc/shared/ptrQueue.hpp"
#include "memory/allocation.hpp"

@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "gc/g1/g1RedirtyCardsQueue.hpp"
#include "gc/shared/bufferNode.hpp"
#include "runtime/atomic.hpp"
#include "utilities/debug.hpp"
#include "utilities/macros.hpp"

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2023, 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
@ -25,6 +25,7 @@
#ifndef SHARE_GC_G1_G1REDIRTYCARDSQUEUE_HPP
#define SHARE_GC_G1_G1REDIRTYCARDSQUEUE_HPP
#include "gc/shared/bufferNode.hpp"
#include "gc/shared/bufferNodeList.hpp"
#include "gc/shared/ptrQueue.hpp"
#include "memory/padded.hpp"

@ -43,9 +43,9 @@
#include "gc/g1/heapRegion.inline.hpp"
#include "gc/g1/heapRegionManager.inline.hpp"
#include "gc/g1/heapRegionRemSet.inline.hpp"
#include "gc/shared/bufferNode.hpp"
#include "gc/shared/bufferNodeList.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
#include "gc/shared/ptrQueue.hpp"
#include "jfr/jfrEvents.hpp"
#include "memory/iterator.hpp"
#include "memory/resourceArea.hpp"

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2023, 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
@ -25,6 +25,7 @@
#ifndef SHARE_GC_G1_G1SATBMARKQUEUESET_HPP
#define SHARE_GC_G1_G1SATBMARKQUEUESET_HPP
#include "gc/shared/bufferNode.hpp"
#include "gc/shared/satbMarkQueue.hpp"
class Monitor;

@ -40,6 +40,7 @@
#include "gc/g1/g1YoungGCPostEvacuateTasks.hpp"
#include "gc/g1/heapRegion.inline.hpp"
#include "gc/g1/heapRegionRemSet.inline.hpp"
#include "gc/shared/bufferNode.hpp"
#include "gc/shared/preservedMarks.inline.hpp"
#include "jfr/jfrEvents.hpp"
#include "oops/access.inline.hpp"

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2023, 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
@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "gc/g1/heapRegionBounds.inline.hpp"
#include "gc/g1/jvmFlagConstraintsG1.hpp"
#include "gc/shared/bufferNode.hpp"
#include "gc/shared/ptrQueue.hpp"
#include "runtime/globals_extension.hpp"
#include "utilities/globalDefinitions.hpp"

@ -0,0 +1,71 @@
/*
* Copyright (c) 2023, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "gc/shared/bufferNode.hpp"
#include "utilities/debug.hpp"
#include "memory/allocation.inline.hpp"
#include <new>
BufferNode::AllocatorConfig::AllocatorConfig(size_t size)
: _buffer_capacity(size)
{
assert(size >= 1, "Invalid buffer capacity %zu", size);
assert(size <= max_size(), "Invalid buffer capacity %zu", size);
}
void* BufferNode::AllocatorConfig::allocate() {
size_t byte_size = buffer_capacity() * sizeof(void*);
return NEW_C_HEAP_ARRAY(char, buffer_offset() + byte_size, mtGC);
}
void BufferNode::AllocatorConfig::deallocate(void* node) {
assert(node != nullptr, "precondition");
FREE_C_HEAP_ARRAY(char, node);
}
BufferNode::Allocator::Allocator(const char* name, size_t buffer_capacity) :
_config(buffer_capacity),
_free_list(name, &_config)
{}
size_t BufferNode::Allocator::free_count() const {
return _free_list.free_count();
}
BufferNode* BufferNode::Allocator::allocate() {
auto internal_capacity = static_cast<InternalSizeType>(buffer_capacity());
return ::new (_free_list.allocate()) BufferNode(internal_capacity);
}
void BufferNode::Allocator::release(BufferNode* node) {
assert(node != nullptr, "precondition");
assert(node->next() == nullptr, "precondition");
assert(node->capacity() == buffer_capacity(),
"Wrong size %zu, expected %zu", node->capacity(), buffer_capacity());
node->~BufferNode();
_free_list.release(node);
}

@ -0,0 +1,139 @@
/*
* Copyright (c) 2023, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_GC_SHARED_BUFFERNODE_HPP
#define SHARE_GC_SHARED_BUFFERNODE_HPP
#include "gc/shared/freeListAllocator.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/lockFreeStack.hpp"
#include "utilities/macros.hpp"
#include <limits>
class BufferNode {
using InternalSizeType = LP64_ONLY(uint32_t) NOT_LP64(uint16_t);
static_assert(sizeof(InternalSizeType) <= sizeof(size_t), "assumption");
InternalSizeType _index;
InternalSizeType _capacity;
BufferNode* volatile _next;
void* _buffer[1]; // Pseudo flexible array member.
BufferNode(InternalSizeType capacity)
: _index(capacity), _capacity(capacity), _next(nullptr)
{}
~BufferNode() = default;
NONCOPYABLE(BufferNode);
static size_t buffer_offset() {
return offset_of(BufferNode, _buffer);
}
public:
static constexpr size_t max_size() {
return std::numeric_limits<InternalSizeType>::max();
}
static BufferNode* volatile* next_ptr(BufferNode& bn) { return &bn._next; }
typedef LockFreeStack<BufferNode, &next_ptr> Stack;
BufferNode* next() const { return _next; }
void set_next(BufferNode* n) { _next = n; }
size_t index() const { return _index; }
void set_index(size_t i) {
assert(i <= capacity(), "precondition");
_index = static_cast<InternalSizeType>(i);
}
size_t capacity() const { return _capacity; }
bool is_empty() const { return index() == capacity(); }
size_t size() const { return capacity() - index(); }
// Return the BufferNode containing the buffer, WITHOUT setting its index.
static BufferNode* make_node_from_buffer(void** buffer) {
char* base = reinterpret_cast<char*>(buffer) - buffer_offset();
return reinterpret_cast<BufferNode*>(base);
}
// Return the BufferNode containing the buffer, after setting its index.
static BufferNode* make_node_from_buffer(void** buffer, size_t index) {
BufferNode* node = make_node_from_buffer(buffer);
node->set_index(index);
return node;
}
// Return the buffer for node.
static void** make_buffer_from_node(BufferNode *node) {
// &_buffer[0] might lead to index out of bounds warnings.
return reinterpret_cast<void**>(
reinterpret_cast<char*>(node) + buffer_offset());
}
class AllocatorConfig;
class Allocator; // Free-list based allocator.
class TestSupport; // Unit test support.
};
// We use BufferNode::AllocatorConfig to set the allocation options for the
// FreeListAllocator.
class BufferNode::AllocatorConfig : public FreeListConfig {
const size_t _buffer_capacity;
public:
explicit AllocatorConfig(size_t size);
~AllocatorConfig() = default;
void* allocate() override;
void deallocate(void* node) override;
size_t buffer_capacity() const { return _buffer_capacity; }
};
class BufferNode::Allocator {
friend class TestSupport;
AllocatorConfig _config;
FreeListAllocator _free_list;
NONCOPYABLE(Allocator);
public:
Allocator(const char* name, size_t buffer_capacity);
~Allocator() = default;
size_t buffer_capacity() const { return _config.buffer_capacity(); }
size_t free_count() const;
BufferNode* allocate();
void release(BufferNode* node);
};
#endif // SHARE_GC_SHARED_BUFFERNODE_HPP

@ -23,10 +23,8 @@
*/
#include "precompiled.hpp"
#include "gc/shared/bufferNode.hpp"
#include "gc/shared/ptrQueue.hpp"
#include "memory/allocation.inline.hpp"
#include <new>
PtrQueue::PtrQueue(PtrQueueSet* qset) :
_index(0),
@ -45,46 +43,6 @@ size_t PtrQueue::current_capacity() const {
}
}
BufferNode::AllocatorConfig::AllocatorConfig(size_t size)
: _buffer_capacity(size)
{
assert(size >= 1, "Invalid buffer capacity %zu", size);
assert(size <= max_size(), "Invalid buffer capacity %zu", size);
}
void* BufferNode::AllocatorConfig::allocate() {
size_t byte_size = buffer_capacity() * sizeof(void*);
return NEW_C_HEAP_ARRAY(char, buffer_offset() + byte_size, mtGC);
}
void BufferNode::AllocatorConfig::deallocate(void* node) {
assert(node != nullptr, "precondition");
FREE_C_HEAP_ARRAY(char, node);
}
BufferNode::Allocator::Allocator(const char* name, size_t buffer_capacity) :
_config(buffer_capacity),
_free_list(name, &_config)
{}
size_t BufferNode::Allocator::free_count() const {
return _free_list.free_count();
}
BufferNode* BufferNode::Allocator::allocate() {
auto internal_capacity = static_cast<InternalSizeType>(buffer_capacity());
return ::new (_free_list.allocate()) BufferNode(internal_capacity);
}
void BufferNode::Allocator::release(BufferNode* node) {
assert(node != nullptr, "precondition");
assert(node->next() == nullptr, "precondition");
assert(node->capacity() == buffer_capacity(),
"Wrong size %zu, expected %zu", node->capacity(), buffer_capacity());
node->~BufferNode();
_free_list.release(node);
}
PtrQueueSet::PtrQueueSet(BufferNode::Allocator* allocator) :
_allocator(allocator)
{}

@ -25,21 +25,17 @@
#ifndef SHARE_GC_SHARED_PTRQUEUE_HPP
#define SHARE_GC_SHARED_PTRQUEUE_HPP
#include "gc/shared/freeListAllocator.hpp"
#include "memory/padded.hpp"
#include "gc/shared/bufferNode.hpp"
#include "utilities/align.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/lockFreeStack.hpp"
#include "utilities/sizes.hpp"
#include <limits>
// There are various techniques that require threads to be able to log
// addresses. For example, a generational write barrier might log
// the addresses of modified old-generation objects. This type supports
// this operation.
class BufferNode;
class PtrQueueSet;
class PtrQueue {
friend class VMStructs;
@ -111,109 +107,6 @@ protected:
static ByteSize byte_width_of_buf() { return in_ByteSize(_element_size); }
};
class BufferNode {
using InternalSizeType = LP64_ONLY(uint32_t) NOT_LP64(uint16_t);
static_assert(sizeof(InternalSizeType) <= sizeof(size_t), "assumption");
InternalSizeType _index;
InternalSizeType _capacity;
BufferNode* volatile _next;
void* _buffer[1]; // Pseudo flexible array member.
BufferNode(InternalSizeType capacity)
: _index(capacity), _capacity(capacity), _next(nullptr)
{}
~BufferNode() = default;
NONCOPYABLE(BufferNode);
static size_t buffer_offset() {
return offset_of(BufferNode, _buffer);
}
public:
static constexpr size_t max_size() {
return std::numeric_limits<InternalSizeType>::max();
}
static BufferNode* volatile* next_ptr(BufferNode& bn) { return &bn._next; }
typedef LockFreeStack<BufferNode, &next_ptr> Stack;
BufferNode* next() const { return _next; }
void set_next(BufferNode* n) { _next = n; }
size_t index() const { return _index; }
void set_index(size_t i) {
assert(i <= capacity(), "precondition");
_index = static_cast<InternalSizeType>(i);
}
size_t capacity() const { return _capacity; }
bool is_empty() const { return index() == capacity(); }
size_t size() const { return capacity() - index(); }
// Return the BufferNode containing the buffer, WITHOUT setting its index.
static BufferNode* make_node_from_buffer(void** buffer) {
char* base = reinterpret_cast<char*>(buffer) - buffer_offset();
return reinterpret_cast<BufferNode*>(base);
}
// Return the BufferNode containing the buffer, after setting its index.
static BufferNode* make_node_from_buffer(void** buffer, size_t index) {
BufferNode* node = make_node_from_buffer(buffer);
node->set_index(index);
return node;
}
// Return the buffer for node.
static void** make_buffer_from_node(BufferNode *node) {
// &_buffer[0] might lead to index out of bounds warnings.
return reinterpret_cast<void**>(
reinterpret_cast<char*>(node) + buffer_offset());
}
class AllocatorConfig;
class Allocator; // Free-list based allocator.
class TestSupport; // Unit test support.
};
// We use BufferNode::AllocatorConfig to set the allocation options for the
// FreeListAllocator.
class BufferNode::AllocatorConfig : public FreeListConfig {
const size_t _buffer_capacity;
public:
explicit AllocatorConfig(size_t size);
~AllocatorConfig() = default;
void* allocate() override;
void deallocate(void* node) override;
size_t buffer_capacity() const { return _buffer_capacity; }
};
class BufferNode::Allocator {
friend class TestSupport;
AllocatorConfig _config;
FreeListAllocator _free_list;
NONCOPYABLE(Allocator);
public:
Allocator(const char* name, size_t buffer_capacity);
~Allocator() = default;
size_t buffer_capacity() const { return _config.buffer_capacity(); }
size_t free_count() const;
BufferNode* allocate();
void release(BufferNode* node);
};
// A PtrQueueSet represents resources common to a set of pointer queues.
// In particular, the individual queues allocate buffers from this shared
// set, and return completed buffers to the set.

@ -26,6 +26,7 @@
#define SHARE_GC_SHENANDOAH_SHENANDOAHBARRIERSET_HPP
#include "gc/shared/barrierSet.hpp"
#include "gc/shared/bufferNode.hpp"
#include "gc/shenandoah/shenandoahSATBMarkQueueSet.hpp"
class ShenandoahHeap;

@ -25,6 +25,7 @@
#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHSATBMARKQUEUESET_HPP
#define SHARE_GC_SHENANDOAH_SHENANDOAHSATBMARKQUEUESET_HPP
#include "gc/shared/bufferNode.hpp"
#include "gc/shared/satbMarkQueue.hpp"
#include "gc/shenandoah/shenandoahHeap.hpp"
#include "runtime/javaThread.hpp"

@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
#include "gc/shared/ptrQueue.hpp"
#include "gc/shared/bufferNode.hpp"
#include "memory/allocation.hpp"
#include "runtime/atomic.hpp"
#include "runtime/interfaceSupport.inline.hpp"
@ -51,7 +51,7 @@ typedef BufferNode::TestSupport::AllocatorThread AllocatorThread;
typedef BufferNode::TestSupport::ProcessorThread ProcessorThread;
// Some basic testing of BufferNode::Allocator.
TEST_VM(PtrQueueBufferAllocatorTest, test) {
TEST_VM(BufferNodeAllocatorTest, test) {
const size_t buffer_capacity = 256;
BufferNode::Allocator allocator("Test Buffer Allocator", buffer_capacity);
ASSERT_EQ(buffer_capacity, allocator.buffer_capacity());
@ -233,7 +233,7 @@ static void run_test(BufferNode::Allocator* allocator, CompletedList* cbl) {
tty->print_cr("allocator free count: " SIZE_FORMAT, allocator->free_count());
}
TEST_VM(PtrQueueBufferAllocatorTest, stress_free_list_allocator) {
TEST_VM(BufferNodeAllocatorTest, stress_free_list_allocator) {
const size_t buffer_capacity = 1024;
BufferNode::Allocator allocator("Test Allocator", buffer_capacity);
CompletedList completed;