8285984: G1: Use standard idiom for inlined payload in G1MonotonicArena::Segment

Reviewed-by: aboldtch, tschatzl
This commit is contained in:
Leo Korinth 2025-09-22 14:22:57 +00:00
parent 3c6ef5e27a
commit bf726e8217
3 changed files with 12 additions and 10 deletions

View File

@ -34,7 +34,7 @@ G1MonotonicArena::Segment::Segment(uint slot_size, uint num_slots, Segment* next
_next(next),
_next_allocate(0),
_mem_tag(mem_tag) {
_bottom = ((char*) this) + header_size();
guarantee(is_aligned(this, SegmentPayloadMaxAlignment), "Make sure Segments are always created at correctly aligned memory");
}
G1MonotonicArena::Segment* G1MonotonicArena::Segment::create_segment(uint slot_size,

View File

@ -110,9 +110,10 @@ protected:
void deallocate(void* slot) override { ShouldNotReachHere(); }
};
static constexpr uint SegmentPayloadMaxAlignment = 8;
// A single segment/arena containing _num_slots blocks of memory of _slot_size.
// Segments can be linked together using a singly linked list.
class G1MonotonicArena::Segment {
class alignas(SegmentPayloadMaxAlignment) G1MonotonicArena::Segment {
const uint _slot_size;
const uint _num_slots;
Segment* volatile _next;
@ -122,16 +123,15 @@ class G1MonotonicArena::Segment {
uint volatile _next_allocate;
const MemTag _mem_tag;
char* _bottom; // Actual data.
// Do not add class member variables beyond this point
static size_t header_size() { return align_up(sizeof(Segment), DEFAULT_PADDING_SIZE); }
static size_t header_size() { return align_up(sizeof(Segment), SegmentPayloadMaxAlignment); }
static size_t payload_size(uint slot_size, uint num_slots) {
// The cast (size_t) is required to guard against overflow wrap around.
return (size_t)slot_size * num_slots;
// The cast is required to guard against overflow wrap around.
return static_cast<size_t>(slot_size) * num_slots;
}
void* payload(size_t octet) { return &reinterpret_cast<char*>(this)[header_size() + octet]; }
size_t payload_size() const { return payload_size(_slot_size, _num_slots); }
NONCOPYABLE(Segment);
@ -156,7 +156,7 @@ public:
_next_allocate = 0;
assert(next != this, " loop condition");
set_next(next);
memset((void*)_bottom, 0, payload_size());
memset(payload(0), 0, payload_size());
}
uint slot_size() const { return _slot_size; }
@ -179,6 +179,7 @@ public:
bool is_full() const { return _next_allocate >= _num_slots; }
};
static_assert(alignof(G1MonotonicArena::Segment) >= SegmentPayloadMaxAlignment, "assert alignment of Segment (and indirectly its payload)");
// Set of (free) Segments. The assumed usage is that allocation
// to it and removal of segments is strictly separate, but every action may be
@ -235,6 +236,7 @@ public:
assert(_initial_num_slots > 0, "Must be");
assert(_max_num_slots > 0, "Must be");
assert(_slot_alignment > 0, "Must be");
assert(SegmentPayloadMaxAlignment % _slot_alignment == 0, "ensure that _slot_alignment is a divisor of SegmentPayloadMaxAlignment");
}
virtual uint next_num_slots(uint prev_num_slots) const {

View File

@ -39,7 +39,7 @@ inline void* G1MonotonicArena::Segment::allocate_slot() {
if (result >= _num_slots) {
return nullptr;
}
void* r = _bottom + (size_t)result * _slot_size;
void* r = payload(static_cast<size_t>(result) * _slot_size);
return r;
}