8371667: Shenandoah: Re-design alloc request type enum for better efficiency and cleaner code

Reviewed-by: shade, kdnilsen
This commit is contained in:
Xiaolong Peng 2025-11-24 22:10:10 +00:00
parent 507a6d327f
commit e00dec5808
3 changed files with 70 additions and 97 deletions

View File

@ -31,15 +31,37 @@
class ShenandoahAllocRequest : StackObj {
public:
enum Type {
_alloc_shared, // Allocate common, outside of TLAB
_alloc_shared_gc, // Allocate common, outside of GCLAB/PLAB
_alloc_cds, // Allocate for CDS
_alloc_tlab, // Allocate TLAB
_alloc_gclab, // Allocate GCLAB
_alloc_plab, // Allocate PLAB
_ALLOC_LIMIT
};
// Alloc type is an int value with encoded bits in scheme as:
// [x|xx|xx|xx]
// ^---- Requester:
// 00 -- mutator
// 10 -- mutator (CDS)
// 01 -- GC
// ^------- Purpose:
// 00 -- shared
// 01 -- TLAB/GCLAB
// 11 -- PLAB
// ^---------- Affiliation:
// 00 -- YOUNG
// 01 -- OLD
// 11 -- OLD, promotion
typedef int Type;
static constexpr int bit_gc_alloc = 1 << 0;
static constexpr int bit_cds_alloc = 1 << 1;
static constexpr int bit_lab_alloc = 1 << 2;
static constexpr int bit_plab_alloc = 1 << 3;
static constexpr int bit_old_alloc = 1 << 4;
static constexpr int bit_promotion_alloc = 1 << 5;
static constexpr Type _alloc_shared = 0;
static constexpr Type _alloc_tlab = bit_lab_alloc;
static constexpr Type _alloc_cds = bit_cds_alloc;
static constexpr Type _alloc_shared_gc = bit_gc_alloc;
static constexpr Type _alloc_shared_gc_old = bit_gc_alloc | bit_old_alloc;
static constexpr Type _alloc_shared_gc_promotion = bit_gc_alloc | bit_old_alloc | bit_promotion_alloc;
static constexpr Type _alloc_gclab = bit_gc_alloc | bit_lab_alloc;
static constexpr Type _alloc_plab = bit_gc_alloc | bit_lab_alloc | bit_plab_alloc | bit_old_alloc;
static const char* alloc_type_to_string(Type type) {
switch (type) {
@ -47,6 +69,10 @@ public:
return "Shared";
case _alloc_shared_gc:
return "Shared GC";
case _alloc_shared_gc_old:
return "Shared GC Old";
case _alloc_shared_gc_promotion:
return "Shared GC Promotion";
case _alloc_cds:
return "CDS";
case _alloc_tlab:
@ -80,20 +106,14 @@ private:
// This is the type of the request.
Type _alloc_type;
// This is the generation which the request is targeting.
ShenandoahAffiliation const _affiliation;
// True if this request is trying to copy any object from young to old (promote).
bool _is_promotion;
#ifdef ASSERT
// Check that this is set before being read.
bool _actual_size_set;
#endif
ShenandoahAllocRequest(size_t _min_size, size_t _requested_size, Type _alloc_type, ShenandoahAffiliation affiliation, bool is_promotion = false) :
ShenandoahAllocRequest(size_t _min_size, size_t _requested_size, Type _alloc_type) :
_min_size(_min_size), _requested_size(_requested_size),
_actual_size(0), _waste(0), _alloc_type(_alloc_type), _affiliation(affiliation), _is_promotion(is_promotion)
_actual_size(0), _waste(0), _alloc_type(_alloc_type)
#ifdef ASSERT
, _actual_size_set(false)
#endif
@ -101,31 +121,34 @@ private:
public:
static inline ShenandoahAllocRequest for_tlab(size_t min_size, size_t requested_size) {
return ShenandoahAllocRequest(min_size, requested_size, _alloc_tlab, ShenandoahAffiliation::YOUNG_GENERATION);
return ShenandoahAllocRequest(min_size, requested_size, _alloc_tlab);
}
static inline ShenandoahAllocRequest for_gclab(size_t min_size, size_t requested_size) {
return ShenandoahAllocRequest(min_size, requested_size, _alloc_gclab, ShenandoahAffiliation::YOUNG_GENERATION);
return ShenandoahAllocRequest(min_size, requested_size, _alloc_gclab);
}
static inline ShenandoahAllocRequest for_plab(size_t min_size, size_t requested_size) {
return ShenandoahAllocRequest(min_size, requested_size, _alloc_plab, ShenandoahAffiliation::OLD_GENERATION);
return ShenandoahAllocRequest(min_size, requested_size, _alloc_plab);
}
static inline ShenandoahAllocRequest for_shared_gc(size_t requested_size, ShenandoahAffiliation affiliation, bool is_promotion = false) {
if (is_promotion) {
assert(affiliation == ShenandoahAffiliation::OLD_GENERATION, "Should only promote to old generation");
return ShenandoahAllocRequest(0, requested_size, _alloc_shared_gc, affiliation, true);
assert(affiliation == OLD_GENERATION, "Should only promote to old generation");
return ShenandoahAllocRequest(0, requested_size, _alloc_shared_gc_promotion);
}
return ShenandoahAllocRequest(0, requested_size, _alloc_shared_gc, affiliation);
if (affiliation == OLD_GENERATION) {
return ShenandoahAllocRequest(0, requested_size, _alloc_shared_gc_old);
}
return ShenandoahAllocRequest(0, requested_size, _alloc_shared_gc);
}
static inline ShenandoahAllocRequest for_shared(size_t requested_size) {
return ShenandoahAllocRequest(0, requested_size, _alloc_shared, ShenandoahAffiliation::YOUNG_GENERATION);
return ShenandoahAllocRequest(0, requested_size, _alloc_shared);
}
static inline ShenandoahAllocRequest for_cds(size_t requested_size) {
return ShenandoahAllocRequest(0, requested_size, _alloc_cds, ShenandoahAffiliation::YOUNG_GENERATION);
return ShenandoahAllocRequest(0, requested_size, _alloc_cds);
}
inline size_t size() const {
@ -167,71 +190,35 @@ public:
}
inline bool is_mutator_alloc() const {
switch (_alloc_type) {
case _alloc_tlab:
case _alloc_shared:
case _alloc_cds:
return true;
case _alloc_gclab:
case _alloc_plab:
case _alloc_shared_gc:
return false;
default:
ShouldNotReachHere();
return false;
}
return (_alloc_type & bit_gc_alloc) == 0;
}
inline bool is_gc_alloc() const {
switch (_alloc_type) {
case _alloc_tlab:
case _alloc_shared:
case _alloc_cds:
return false;
case _alloc_gclab:
case _alloc_plab:
case _alloc_shared_gc:
return true;
default:
ShouldNotReachHere();
return false;
}
return (_alloc_type & bit_gc_alloc) != 0;
}
inline bool is_lab_alloc() const {
switch (_alloc_type) {
case _alloc_tlab:
case _alloc_gclab:
case _alloc_plab:
return true;
case _alloc_shared:
case _alloc_shared_gc:
case _alloc_cds:
return false;
default:
ShouldNotReachHere();
return false;
}
return (_alloc_type & bit_lab_alloc) != 0;
}
bool is_old() const {
return _affiliation == OLD_GENERATION;
inline bool is_old() const {
return (_alloc_type & bit_old_alloc) != 0;
}
bool is_young() const {
return _affiliation == YOUNG_GENERATION;
inline bool is_young() const {
return (_alloc_type & bit_old_alloc) == 0;
}
ShenandoahAffiliation affiliation() const {
return _affiliation;
inline ShenandoahAffiliation affiliation() const {
return (_alloc_type & bit_old_alloc) == 0 ? YOUNG_GENERATION : OLD_GENERATION ;
}
const char* affiliation_name() const {
return shenandoah_affiliation_name(_affiliation);
return shenandoah_affiliation_name(affiliation());
}
bool is_promotion() const {
return _is_promotion;
inline bool is_promotion() const {
return (_alloc_type & bit_promotion_alloc) != 0;
}
};

View File

@ -1311,19 +1311,11 @@ HeapWord* ShenandoahFreeSet::allocate_single(ShenandoahAllocRequest& req, bool&
// Overwrite with non-zero (non-null) values only if necessary for allocation bookkeeping.
switch (req.type()) {
case ShenandoahAllocRequest::_alloc_tlab:
case ShenandoahAllocRequest::_alloc_shared:
case ShenandoahAllocRequest::_alloc_cds:
return allocate_for_mutator(req, in_new_region);
case ShenandoahAllocRequest::_alloc_gclab:
case ShenandoahAllocRequest::_alloc_plab:
case ShenandoahAllocRequest::_alloc_shared_gc:
return allocate_for_collector(req, in_new_region);
default:
ShouldNotReachHere();
if (req.is_mutator_alloc()) {
return allocate_for_mutator(req, in_new_region);
} else {
return allocate_for_collector(req, in_new_region);
}
return nullptr;
}
HeapWord* ShenandoahFreeSet::allocate_for_mutator(ShenandoahAllocRequest &req, bool &in_new_region) {
@ -1619,21 +1611,13 @@ HeapWord* ShenandoahFreeSet::try_allocate_in(ShenandoahHeapRegion* r, Shenandoah
if (req.is_mutator_alloc()) {
request_generation = _heap->mode()->is_generational()? _heap->young_generation(): _heap->global_generation();
orig_partition = ShenandoahFreeSetPartitionId::Mutator;
} else if (req.type() == ShenandoahAllocRequest::_alloc_gclab) {
request_generation = _heap->mode()->is_generational()? _heap->young_generation(): _heap->global_generation();
orig_partition = ShenandoahFreeSetPartitionId::Collector;
} else if (req.type() == ShenandoahAllocRequest::_alloc_plab) {
} else if (req.is_old()) {
request_generation = _heap->old_generation();
orig_partition = ShenandoahFreeSetPartitionId::OldCollector;
} else {
assert(req.type() == ShenandoahAllocRequest::_alloc_shared_gc, "Unexpected allocation type");
if (req.is_old()) {
request_generation = _heap->old_generation();
orig_partition = ShenandoahFreeSetPartitionId::OldCollector;
} else {
request_generation = _heap->mode()->is_generational()? _heap->young_generation(): _heap->global_generation();
orig_partition = ShenandoahFreeSetPartitionId::Collector;
}
// Not old collector alloc, so this is a young collector gclab or shared allocation
request_generation = _heap->mode()->is_generational()? _heap->young_generation(): _heap->global_generation();
orig_partition = ShenandoahFreeSetPartitionId::Collector;
}
if (alloc_capacity(r) < PLAB::min_size() * HeapWordSize) {
// Regardless of whether this allocation succeeded, if the remaining memory is less than PLAB:min_size(), retire this region.

View File

@ -129,6 +129,8 @@ inline void ShenandoahHeapRegion::adjust_alloc_metadata(ShenandoahAllocRequest::
switch (type) {
case ShenandoahAllocRequest::_alloc_shared:
case ShenandoahAllocRequest::_alloc_shared_gc:
case ShenandoahAllocRequest::_alloc_shared_gc_old:
case ShenandoahAllocRequest::_alloc_shared_gc_promotion:
case ShenandoahAllocRequest::_alloc_cds:
// Counted implicitly by tlab/gclab allocs
break;