8357053: ZGC: Improved utility for ZPageAge

Co-authored-by: Axel Boldt-Christmas <aboldtch@openjdk.org>
Reviewed-by: sjohanss, stefank
This commit is contained in:
Joel Sikström 2025-06-09 09:03:12 +00:00
parent 52338c94f6
commit 1c72b350e4
14 changed files with 191 additions and 58 deletions

View File

@ -23,6 +23,7 @@
#include "gc/z/zAllocator.hpp" #include "gc/z/zAllocator.hpp"
#include "gc/z/zObjectAllocator.hpp" #include "gc/z/zObjectAllocator.hpp"
#include "gc/z/zPageAge.inline.hpp"
ZAllocatorEden* ZAllocator::_eden; ZAllocatorEden* ZAllocator::_eden;
ZAllocatorForRelocation* ZAllocator::_relocation[ZAllocator::_relocation_allocators]; ZAllocatorForRelocation* ZAllocator::_relocation[ZAllocator::_relocation_allocators];
@ -47,7 +48,7 @@ ZPageAge ZAllocatorForRelocation::install() {
for (uint i = 0; i < ZAllocator::_relocation_allocators; ++i) { for (uint i = 0; i < ZAllocator::_relocation_allocators; ++i) {
if (_relocation[i] == nullptr) { if (_relocation[i] == nullptr) {
_relocation[i] = this; _relocation[i] = this;
return static_cast<ZPageAge>(i + 1); return to_zpageage(i + 1);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -35,7 +35,7 @@ class ZPage;
class ZAllocator { class ZAllocator {
public: public:
static constexpr uint _relocation_allocators = static_cast<uint>(ZPageAge::old); static constexpr uint _relocation_allocators = ZPageAgeCount - 1;
protected: protected:
ZObjectAllocator _object_allocator; ZObjectAllocator _object_allocator;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -28,13 +28,14 @@
#include "gc/z/zAddress.inline.hpp" #include "gc/z/zAddress.inline.hpp"
#include "gc/z/zHeap.hpp" #include "gc/z/zHeap.hpp"
#include "gc/z/zPageAge.inline.hpp"
inline ZAllocatorEden* ZAllocator::eden() { inline ZAllocatorEden* ZAllocator::eden() {
return _eden; return _eden;
} }
inline ZAllocatorForRelocation* ZAllocator::relocation(ZPageAge page_age) { inline ZAllocatorForRelocation* ZAllocator::relocation(ZPageAge page_age) {
return _relocation[static_cast<uint>(page_age) - 1]; return _relocation[untype(page_age - 1)];
} }
inline ZAllocatorForRelocation* ZAllocator::old() { inline ZAllocatorForRelocation* ZAllocator::old() {

View File

@ -41,6 +41,7 @@
#include "gc/z/zHeap.inline.hpp" #include "gc/z/zHeap.inline.hpp"
#include "gc/z/zJNICritical.hpp" #include "gc/z/zJNICritical.hpp"
#include "gc/z/zMark.inline.hpp" #include "gc/z/zMark.inline.hpp"
#include "gc/z/zPageAge.inline.hpp"
#include "gc/z/zPageAllocator.hpp" #include "gc/z/zPageAllocator.hpp"
#include "gc/z/zRelocationSet.inline.hpp" #include "gc/z/zRelocationSet.inline.hpp"
#include "gc/z/zRelocationSetSelector.inline.hpp" #include "gc/z/zRelocationSetSelector.inline.hpp"
@ -699,11 +700,10 @@ uint ZGenerationYoung::compute_tenuring_threshold(ZRelocationSetSelectorStats st
uint last_populated_age = 0; uint last_populated_age = 0;
size_t last_populated_live = 0; size_t last_populated_live = 0;
for (uint i = 0; i <= ZPageAgeMax; ++i) { for (ZPageAge age : ZPageAgeRange()) {
const ZPageAge age = static_cast<ZPageAge>(i);
const size_t young_live = stats.small(age).live() + stats.medium(age).live() + stats.large(age).live(); const size_t young_live = stats.small(age).live() + stats.medium(age).live() + stats.large(age).live();
if (young_live > 0) { if (young_live > 0) {
last_populated_age = i; last_populated_age = untype(age);
last_populated_live = young_live; last_populated_live = young_live;
if (young_live_last > 0) { if (young_live_last > 0) {
young_life_expectancy_sum += double(young_live) / double(young_live_last); young_life_expectancy_sum += double(young_live) / double(young_live_last);
@ -842,8 +842,8 @@ void ZGenerationYoung::mark_start() {
// Retire allocating pages // Retire allocating pages
ZAllocator::eden()->retire_pages(); ZAllocator::eden()->retire_pages();
for (ZPageAge i = ZPageAge::survivor1; i <= ZPageAge::survivor14; i = static_cast<ZPageAge>(static_cast<uint>(i) + 1)) { for (ZPageAge age : ZPageAgeRangeSurvivor) {
ZAllocator::relocation(i)->retire_pages(); ZAllocator::relocation(age)->retire_pages();
} }
// Reset allocated/reclaimed/used statistics // Reset allocated/reclaimed/used statistics

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -24,6 +24,7 @@
#ifndef SHARE_GC_Z_ZPAGEAGE_HPP #ifndef SHARE_GC_Z_ZPAGEAGE_HPP
#define SHARE_GC_Z_ZPAGEAGE_HPP #define SHARE_GC_Z_ZPAGEAGE_HPP
#include "utilities/enumIterator.hpp"
#include "utilities/globalDefinitions.hpp" #include "utilities/globalDefinitions.hpp"
enum class ZPageAge : uint8_t { enum class ZPageAge : uint8_t {
@ -45,6 +46,19 @@ enum class ZPageAge : uint8_t {
old old
}; };
constexpr uint ZPageAgeMax = static_cast<uint>(ZPageAge::old); constexpr uint ZPageAgeCount = static_cast<uint>(ZPageAge::old) + 1;
constexpr ZPageAge ZPageAgeLastPlusOne = static_cast<ZPageAge>(ZPageAgeCount);
ENUMERATOR_RANGE(ZPageAge,
ZPageAge::eden,
ZPageAge::old);
using ZPageAgeRange = EnumRange<ZPageAge>;
constexpr ZPageAgeRange ZPageAgeRangeEden = ZPageAgeRange::create<ZPageAge::eden, ZPageAge::survivor1>();
constexpr ZPageAgeRange ZPageAgeRangeYoung = ZPageAgeRange::create<ZPageAge::eden, ZPageAge::old>();
constexpr ZPageAgeRange ZPageAgeRangeSurvivor = ZPageAgeRange::create<ZPageAge::survivor1, ZPageAge::old>();
constexpr ZPageAgeRange ZPageAgeRangeRelocation = ZPageAgeRange::create<ZPageAge::survivor1, ZPageAgeLastPlusOne>();
constexpr ZPageAgeRange ZPageAgeRangeOld = ZPageAgeRange::create<ZPageAge::old, ZPageAgeLastPlusOne>();
#endif // SHARE_GC_Z_ZPAGEAGE_HPP #endif // SHARE_GC_Z_ZPAGEAGE_HPP

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2025, 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_Z_ZPAGEAGE_INLINE_HPP
#define SHARE_GC_Z_ZPAGEAGE_INLINE_HPP
#include "gc/z/zPageAge.hpp"
#include "utilities/checkedCast.hpp"
#include <type_traits>
inline uint untype(ZPageAge age) {
return static_cast<uint>(age);
}
inline ZPageAge to_zpageage(uint age) {
assert(age < ZPageAgeCount, "Invalid age");
return static_cast<ZPageAge>(age);
}
inline ZPageAge operator+(ZPageAge age, size_t size) {
const auto size_value = checked_cast<std::underlying_type_t<ZPageAge>>(size);
return to_zpageage(untype(age) + size_value);
}
inline ZPageAge operator-(ZPageAge age, size_t size) {
const auto size_value = checked_cast<std::underlying_type_t<ZPageAge>>(size);
return to_zpageage(untype(age) - size_value);
}
#endif // SHARE_GC_Z_ZPAGEAGE_INLINE_HPP

View File

@ -488,11 +488,11 @@ public:
} }
ZPage* shared(ZPageAge age) { ZPage* shared(ZPageAge age) {
return _shared[static_cast<uint>(age) - 1]; return _shared[untype(age - 1)];
} }
void set_shared(ZPageAge age, ZPage* page) { void set_shared(ZPageAge age, ZPage* page) {
_shared[static_cast<uint>(age) - 1] = page; _shared[untype(age - 1)] = page;
} }
ZPage* alloc_and_retire_target_page(ZForwarding* forwarding, ZPage* target) { ZPage* alloc_and_retire_target_page(ZForwarding* forwarding, ZPage* target) {
@ -570,11 +570,11 @@ private:
ZPage* target(ZPageAge age) { ZPage* target(ZPageAge age) {
return _target[static_cast<uint>(age) - 1]; return _target[untype(age - 1)];
} }
void set_target(ZPageAge age, ZPage* page) { void set_target(ZPageAge age, ZPage* page) {
_target[static_cast<uint>(age) - 1] = page; _target[untype(age - 1)] = page;
} }
size_t object_alignment() const { size_t object_alignment() const {
@ -1232,12 +1232,12 @@ ZPageAge ZRelocate::compute_to_age(ZPageAge from_age) {
return ZPageAge::old; return ZPageAge::old;
} }
const uint age = static_cast<uint>(from_age); const uint age = untype(from_age);
if (age >= ZGeneration::young()->tenuring_threshold()) { if (age >= ZGeneration::young()->tenuring_threshold()) {
return ZPageAge::old; return ZPageAge::old;
} }
return static_cast<ZPageAge>(age + 1); return to_zpageage(age + 1);
} }
class ZFlipAgePagesTask : public ZTask { class ZFlipAgePagesTask : public ZTask {

View File

@ -25,6 +25,7 @@
#include "gc/z/zArray.inline.hpp" #include "gc/z/zArray.inline.hpp"
#include "gc/z/zForwarding.inline.hpp" #include "gc/z/zForwarding.inline.hpp"
#include "gc/z/zPage.inline.hpp" #include "gc/z/zPage.inline.hpp"
#include "gc/z/zPageAge.inline.hpp"
#include "gc/z/zRelocationSetSelector.inline.hpp" #include "gc/z/zRelocationSetSelector.inline.hpp"
#include "jfr/jfrEvents.hpp" #include "jfr/jfrEvents.hpp"
#include "logging/log.hpp" #include "logging/log.hpp"
@ -117,8 +118,8 @@ void ZRelocationSetSelectorGroup::select_inner() {
const int npages = _live_pages.length(); const int npages = _live_pages.length();
int selected_from = 0; int selected_from = 0;
int selected_to = 0; int selected_to = 0;
size_t npages_selected[ZPageAgeMax + 1] = { 0 }; size_t npages_selected[ZPageAgeCount] = { 0 };
size_t selected_live_bytes[ZPageAgeMax + 1] = { 0 }; size_t selected_live_bytes[ZPageAgeCount] = { 0 };
size_t selected_forwarding_entries = 0; size_t selected_forwarding_entries = 0;
size_t from_live_bytes = 0; size_t from_live_bytes = 0;
@ -149,8 +150,8 @@ void ZRelocationSetSelectorGroup::select_inner() {
if (diff_reclaimable > _fragmentation_limit) { if (diff_reclaimable > _fragmentation_limit) {
selected_from = from; selected_from = from;
selected_to = to; selected_to = to;
selected_live_bytes[static_cast<uint>(page->age())] += page_live_bytes; selected_live_bytes[untype(page->age())] += page_live_bytes;
npages_selected[static_cast<uint>(page->age())] += 1; npages_selected[untype(page->age())] += 1;
selected_forwarding_entries = from_forwarding_entries; selected_forwarding_entries = from_forwarding_entries;
} }
@ -172,7 +173,7 @@ void ZRelocationSetSelectorGroup::select_inner() {
_forwarding_entries = selected_forwarding_entries; _forwarding_entries = selected_forwarding_entries;
// Update statistics // Update statistics
for (uint i = 0; i <= ZPageAgeMax; ++i) { for (uint i = 0; i < ZPageAgeCount; ++i) {
_stats[i]._relocate = selected_live_bytes[i]; _stats[i]._relocate = selected_live_bytes[i];
_stats[i]._npages_selected = npages_selected[i]; _stats[i]._npages_selected = npages_selected[i];
} }
@ -200,7 +201,7 @@ void ZRelocationSetSelectorGroup::select() {
} }
ZRelocationSetSelectorGroupStats s{}; ZRelocationSetSelectorGroupStats s{};
for (uint i = 0; i <= ZPageAgeMax; ++i) { for (uint i = 0; i < ZPageAgeCount; ++i) {
s._npages_candidates += _stats[i].npages_candidates(); s._npages_candidates += _stats[i].npages_candidates();
s._total += _stats[i].total(); s._total += _stats[i].total();
s._empty += _stats[i].empty(); s._empty += _stats[i].empty();
@ -239,8 +240,8 @@ void ZRelocationSetSelector::select() {
ZRelocationSetSelectorStats ZRelocationSetSelector::stats() const { ZRelocationSetSelectorStats ZRelocationSetSelector::stats() const {
ZRelocationSetSelectorStats stats; ZRelocationSetSelectorStats stats;
for (uint i = 0; i <= ZPageAgeMax; ++i) { for (ZPageAge age : ZPageAgeRange()) {
const ZPageAge age = static_cast<ZPageAge>(i); const uint i = untype(age);
stats._small[i] = _small.stats(age); stats._small[i] = _small.stats(age);
stats._medium[i] = _medium.stats(age); stats._medium[i] = _medium.stats(age);
stats._large[i] = _large.stats(age); stats._large[i] = _large.stats(age);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -62,9 +62,9 @@ class ZRelocationSetSelectorStats {
friend class ZRelocationSetSelector; friend class ZRelocationSetSelector;
private: private:
ZRelocationSetSelectorGroupStats _small[ZPageAgeMax + 1]; ZRelocationSetSelectorGroupStats _small[ZPageAgeCount];
ZRelocationSetSelectorGroupStats _medium[ZPageAgeMax + 1]; ZRelocationSetSelectorGroupStats _medium[ZPageAgeCount];
ZRelocationSetSelectorGroupStats _large[ZPageAgeMax + 1]; ZRelocationSetSelectorGroupStats _large[ZPageAgeCount];
size_t _has_relocatable_pages; size_t _has_relocatable_pages;
@ -90,7 +90,7 @@ private:
ZArray<ZPage*> _live_pages; ZArray<ZPage*> _live_pages;
ZArray<ZPage*> _not_selected_pages; ZArray<ZPage*> _not_selected_pages;
size_t _forwarding_entries; size_t _forwarding_entries;
ZRelocationSetSelectorGroupStats _stats[ZPageAgeMax + 1]; ZRelocationSetSelectorGroupStats _stats[ZPageAgeCount];
bool is_disabled(); bool is_disabled();
bool is_selectable(); bool is_selectable();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -29,6 +29,7 @@
#include "gc/z/zArray.inline.hpp" #include "gc/z/zArray.inline.hpp"
#include "gc/z/zGlobals.hpp" #include "gc/z/zGlobals.hpp"
#include "gc/z/zPage.inline.hpp" #include "gc/z/zPage.inline.hpp"
#include "gc/z/zPageAge.inline.hpp"
#include "utilities/powerOfTwo.hpp" #include "utilities/powerOfTwo.hpp"
inline size_t ZRelocationSetSelectorGroupStats::npages_candidates() const { inline size_t ZRelocationSetSelectorGroupStats::npages_candidates() const {
@ -60,15 +61,15 @@ inline bool ZRelocationSetSelectorStats::has_relocatable_pages() const {
} }
inline const ZRelocationSetSelectorGroupStats& ZRelocationSetSelectorStats::small(ZPageAge age) const { inline const ZRelocationSetSelectorGroupStats& ZRelocationSetSelectorStats::small(ZPageAge age) const {
return _small[static_cast<uint>(age)]; return _small[untype(age)];
} }
inline const ZRelocationSetSelectorGroupStats& ZRelocationSetSelectorStats::medium(ZPageAge age) const { inline const ZRelocationSetSelectorGroupStats& ZRelocationSetSelectorStats::medium(ZPageAge age) const {
return _medium[static_cast<uint>(age)]; return _medium[untype(age)];
} }
inline const ZRelocationSetSelectorGroupStats& ZRelocationSetSelectorStats::large(ZPageAge age) const { inline const ZRelocationSetSelectorGroupStats& ZRelocationSetSelectorStats::large(ZPageAge age) const {
return _large[static_cast<uint>(age)]; return _large[untype(age)];
} }
inline bool ZRelocationSetSelectorGroup::pre_filter_page(const ZPage* page, size_t live_bytes) const { inline bool ZRelocationSetSelectorGroup::pre_filter_page(const ZPage* page, size_t live_bytes) const {
@ -113,7 +114,7 @@ inline void ZRelocationSetSelectorGroup::register_live_page(ZPage* page) {
} }
const size_t size = page->size(); const size_t size = page->size();
const uint age = static_cast<uint>(page->age()); const uint age = untype(page->age());
_stats[age]._npages_candidates++; _stats[age]._npages_candidates++;
_stats[age]._total += size; _stats[age]._total += size;
_stats[age]._live += live; _stats[age]._live += live;
@ -122,7 +123,7 @@ inline void ZRelocationSetSelectorGroup::register_live_page(ZPage* page) {
inline void ZRelocationSetSelectorGroup::register_empty_page(ZPage* page) { inline void ZRelocationSetSelectorGroup::register_empty_page(ZPage* page) {
const size_t size = page->size(); const size_t size = page->size();
const uint age = static_cast<uint>(page->age()); const uint age = untype(page->age());
_stats[age]._npages_candidates++; _stats[age]._npages_candidates++;
_stats[age]._total += size; _stats[age]._total += size;
_stats[age]._empty += size; _stats[age]._empty += size;
@ -141,7 +142,7 @@ inline size_t ZRelocationSetSelectorGroup::forwarding_entries() const {
} }
inline const ZRelocationSetSelectorGroupStats& ZRelocationSetSelectorGroup::stats(ZPageAge age) const { inline const ZRelocationSetSelectorGroupStats& ZRelocationSetSelectorGroup::stats(ZPageAge age) const {
return _stats[static_cast<uint>(age)]; return _stats[untype(age)];
} }
inline void ZRelocationSetSelector::register_live_page(ZPage* page) { inline void ZRelocationSetSelector::register_live_page(ZPage* page) {
@ -188,8 +189,7 @@ inline void ZRelocationSetSelector::clear_empty_pages() {
inline size_t ZRelocationSetSelector::total() const { inline size_t ZRelocationSetSelector::total() const {
size_t sum = 0; size_t sum = 0;
for (uint i = 0; i <= ZPageAgeMax; ++i) { for (ZPageAge age : ZPageAgeRange()) {
const ZPageAge age = static_cast<ZPageAge>(i);
sum += _small.stats(age).total() + _medium.stats(age).total() + _large.stats(age).total(); sum += _small.stats(age).total() + _medium.stats(age).total() + _large.stats(age).total();
} }
return sum; return sum;
@ -197,8 +197,7 @@ inline size_t ZRelocationSetSelector::total() const {
inline size_t ZRelocationSetSelector::empty() const { inline size_t ZRelocationSetSelector::empty() const {
size_t sum = 0; size_t sum = 0;
for (uint i = 0; i <= ZPageAgeMax; ++i) { for (ZPageAge age : ZPageAgeRange()) {
const ZPageAge age = static_cast<ZPageAge>(i);
sum += _small.stats(age).empty() + _medium.stats(age).empty() + _large.stats(age).empty(); sum += _small.stats(age).empty() + _medium.stats(age).empty() + _large.stats(age).empty();
} }
return sum; return sum;
@ -206,8 +205,7 @@ inline size_t ZRelocationSetSelector::empty() const {
inline size_t ZRelocationSetSelector::relocate() const { inline size_t ZRelocationSetSelector::relocate() const {
size_t sum = 0; size_t sum = 0;
for (uint i = 0; i <= ZPageAgeMax; ++i) { for (ZPageAge age : ZPageAgeRange()) {
const ZPageAge age = static_cast<ZPageAge>(i);
sum += _small.stats(age).relocate() + _medium.stats(age).relocate() + _large.stats(age).relocate(); sum += _small.stats(age).relocate() + _medium.stats(age).relocate() + _large.stats(age).relocate();
} }
return sum; return sum;

View File

@ -30,6 +30,7 @@
#include "gc/z/zGeneration.inline.hpp" #include "gc/z/zGeneration.inline.hpp"
#include "gc/z/zGlobals.hpp" #include "gc/z/zGlobals.hpp"
#include "gc/z/zNMethodTable.hpp" #include "gc/z/zNMethodTable.hpp"
#include "gc/z/zPageAge.inline.hpp"
#include "gc/z/zPageAllocator.inline.hpp" #include "gc/z/zPageAllocator.inline.hpp"
#include "gc/z/zRelocationSetSelector.inline.hpp" #include "gc/z/zRelocationSetSelector.inline.hpp"
#include "gc/z/zStat.hpp" #include "gc/z/zStat.hpp"
@ -1499,9 +1500,7 @@ void ZStatRelocation::print_page_summary() {
summary.relocate += stats.relocate(); summary.relocate += stats.relocate();
}; };
for (uint i = 0; i <= ZPageAgeMax; ++i) { for (ZPageAge age : ZPageAgeRange()) {
const ZPageAge age = static_cast<ZPageAge>(i);
account_page_size(small_summary, _selector_stats.small(age)); account_page_size(small_summary, _selector_stats.small(age));
account_page_size(medium_summary, _selector_stats.medium(age)); account_page_size(medium_summary, _selector_stats.medium(age));
account_page_size(large_summary, _selector_stats.large(age)); account_page_size(large_summary, _selector_stats.large(age));
@ -1557,13 +1556,13 @@ void ZStatRelocation::print_age_table() {
.center("Large") .center("Large")
.end()); .end());
size_t live[ZPageAgeMax + 1] = {}; size_t live[ZPageAgeCount] = {};
size_t total[ZPageAgeMax + 1] = {}; size_t total[ZPageAgeCount] = {};
uint oldest_none_empty_age = 0; uint oldest_none_empty_age = 0;
for (uint i = 0; i <= ZPageAgeMax; ++i) { for (ZPageAge age : ZPageAgeRange()) {
ZPageAge age = static_cast<ZPageAge>(i); uint i = untype(age);
auto summarize_pages = [&](const ZRelocationSetSelectorGroupStats& stats) { auto summarize_pages = [&](const ZRelocationSetSelectorGroupStats& stats) {
live[i] += stats.live(); live[i] += stats.live();
total[i] += stats.total(); total[i] += stats.total();
@ -1579,7 +1578,7 @@ void ZStatRelocation::print_age_table() {
} }
for (uint i = 0; i <= oldest_none_empty_age; ++i) { for (uint i = 0; i <= oldest_none_empty_age; ++i) {
ZPageAge age = static_cast<ZPageAge>(i); ZPageAge age = to_zpageage(i);
FormatBuffer<> age_str(""); FormatBuffer<> age_str("");
if (age == ZPageAge::eden) { if (age == ZPageAge::eden) {
@ -1791,8 +1790,7 @@ void ZStatHeap::at_select_relocation_set(const ZRelocationSetSelectorStats& stat
ZLocker<ZLock> locker(&_stat_lock); ZLocker<ZLock> locker(&_stat_lock);
size_t live = 0; size_t live = 0;
for (uint i = 0; i <= ZPageAgeMax; ++i) { for (ZPageAge age : ZPageAgeRange()) {
const ZPageAge age = static_cast<ZPageAge>(i);
live += stats.small(age).live() + stats.medium(age).live() + stats.large(age).live(); live += stats.small(age).live() + stats.medium(age).live() + stats.large(age).live();
} }
_at_mark_end.live = live; _at_mark_end.live = live;

View File

@ -113,7 +113,7 @@
\ \
product(int, ZTenuringThreshold, -1, DIAGNOSTIC, \ product(int, ZTenuringThreshold, -1, DIAGNOSTIC, \
"Young generation tenuring threshold, -1 for dynamic computation")\ "Young generation tenuring threshold, -1 for dynamic computation")\
range(-1, static_cast<int>(ZPageAgeMax)) \ range(-1, static_cast<int>(ZPageAgeCount) - 1) \
\ \
develop(bool, ZVerifyOops, false, \ develop(bool, ZVerifyOops, false, \
"Verify accessed oops") \ "Verify accessed oops") \

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,13 +25,14 @@
#ifndef SHARE_UTILITIES_ENUMITERATOR_HPP #ifndef SHARE_UTILITIES_ENUMITERATOR_HPP
#define SHARE_UTILITIES_ENUMITERATOR_HPP #define SHARE_UTILITIES_ENUMITERATOR_HPP
#include <type_traits>
#include <limits>
#include "memory/allStatic.hpp" #include "memory/allStatic.hpp"
#include "metaprogramming/enableIf.hpp" #include "metaprogramming/enableIf.hpp"
#include "metaprogramming/primitiveConversions.hpp" #include "metaprogramming/primitiveConversions.hpp"
#include "utilities/debug.hpp" #include "utilities/debug.hpp"
#include <limits>
#include <type_traits>
// Iteration support for enums. // Iteration support for enums.
// //
// E is enum type, U is underlying type of E. // E is enum type, U is underlying type of E.
@ -147,6 +148,12 @@ public:
assert(value <= end, "out of range"); assert(value <= end, "out of range");
} }
template <T Value>
static constexpr void assert_in_range() {
static_assert(_start <= static_cast<Underlying>(Value), "out of range");
static_assert(static_cast<Underlying>(Value) <= _end, "out of range");
}
// Convert an enumerator value to the corresponding underlying type. // Convert an enumerator value to the corresponding underlying type.
static constexpr Underlying underlying_value(T value) { static constexpr Underlying underlying_value(T value) {
return static_cast<Underlying>(value); return static_cast<Underlying>(value);
@ -229,6 +236,12 @@ class EnumRange {
assert(size() > 0, "empty range"); assert(size() > 0, "empty range");
} }
struct ConstExprConstructTag {};
constexpr EnumRange(T start, T end, ConstExprConstructTag) :
_start(Traits::underlying_value(start)),
_end(Traits::underlying_value(end)) {}
public: public:
using EnumType = T; using EnumType = T;
using Iterator = EnumIterator<T>; using Iterator = EnumIterator<T>;
@ -252,6 +265,14 @@ public:
assert(start <= end, "invalid range"); assert(start <= end, "invalid range");
} }
template <T Start, T End>
static constexpr EnumRange<T> create() {
Traits::template assert_in_range<Start>();
Traits::template assert_in_range<End>();
static_assert(Start <= End, "invalid range");
return EnumRange(Start, End, ConstExprConstructTag{});
}
// Return an iterator for the start of the range. // Return an iterator for the start of the range.
constexpr Iterator begin() const { constexpr Iterator begin() const {
return Iterator(Traits::enumerator(_start)); return Iterator(Traits::enumerator(_start));

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2025, 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 "gc/z/zPageAge.hpp"
#include "unittest.hpp"
TEST(ZPageAgeRangeTest, test) {
ZPageAgeRange rangeEden = ZPageAgeRangeEden;
EXPECT_EQ(rangeEden.first(), ZPageAge::eden);
EXPECT_EQ(rangeEden.last(), ZPageAge::eden);
ZPageAgeRange rangeYoung = ZPageAgeRangeYoung;
EXPECT_EQ(rangeYoung.first(), ZPageAge::eden);
EXPECT_EQ(rangeYoung.last(), ZPageAge::survivor14);
ZPageAgeRange rangeSurvivor = ZPageAgeRangeSurvivor;
EXPECT_EQ(rangeSurvivor.first(), ZPageAge::survivor1);
EXPECT_EQ(rangeSurvivor.last(), ZPageAge::survivor14);
ZPageAgeRange rangeRelocation = ZPageAgeRangeRelocation;
EXPECT_EQ(rangeRelocation.first(), ZPageAge::survivor1);
EXPECT_EQ(rangeRelocation.last(), ZPageAge::old);
ZPageAgeRange rangeOld = ZPageAgeRangeOld;
EXPECT_EQ(rangeOld.first(), ZPageAge::old);
EXPECT_EQ(rangeOld.last(), ZPageAge::old);
}