From bf726e821790fad6ee304c1c36bddedbfe4152ff Mon Sep 17 00:00:00 2001 From: Leo Korinth Date: Mon, 22 Sep 2025 14:22:57 +0000 Subject: [PATCH] 8285984: G1: Use standard idiom for inlined payload in G1MonotonicArena::Segment Reviewed-by: aboldtch, tschatzl --- src/hotspot/share/gc/g1/g1MonotonicArena.cpp | 2 +- src/hotspot/share/gc/g1/g1MonotonicArena.hpp | 18 ++++++++++-------- .../share/gc/g1/g1MonotonicArena.inline.hpp | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1MonotonicArena.cpp b/src/hotspot/share/gc/g1/g1MonotonicArena.cpp index 1ee299e2ee4..a9c6462680f 100644 --- a/src/hotspot/share/gc/g1/g1MonotonicArena.cpp +++ b/src/hotspot/share/gc/g1/g1MonotonicArena.cpp @@ -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, diff --git a/src/hotspot/share/gc/g1/g1MonotonicArena.hpp b/src/hotspot/share/gc/g1/g1MonotonicArena.hpp index 828c7f4e86d..211820c5254 100644 --- a/src/hotspot/share/gc/g1/g1MonotonicArena.hpp +++ b/src/hotspot/share/gc/g1/g1MonotonicArena.hpp @@ -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(slot_size) * num_slots; } + void* payload(size_t octet) { return &reinterpret_cast(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 { diff --git a/src/hotspot/share/gc/g1/g1MonotonicArena.inline.hpp b/src/hotspot/share/gc/g1/g1MonotonicArena.inline.hpp index d4c1aa8c4e3..dd9ccae1849 100644 --- a/src/hotspot/share/gc/g1/g1MonotonicArena.inline.hpp +++ b/src/hotspot/share/gc/g1/g1MonotonicArena.inline.hpp @@ -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(result) * _slot_size); return r; }