From 1c72b350e417bd210dc6b66eba5afe0e3bc6306c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Sikstr=C3=B6m?= Date: Mon, 9 Jun 2025 09:03:12 +0000 Subject: [PATCH] 8357053: ZGC: Improved utility for ZPageAge Co-authored-by: Axel Boldt-Christmas Reviewed-by: sjohanss, stefank --- src/hotspot/share/gc/z/zAllocator.cpp | 3 +- src/hotspot/share/gc/z/zAllocator.hpp | 4 +- src/hotspot/share/gc/z/zAllocator.inline.hpp | 5 +- src/hotspot/share/gc/z/zGeneration.cpp | 10 ++-- src/hotspot/share/gc/z/zPageAge.hpp | 18 ++++++- src/hotspot/share/gc/z/zPageAge.inline.hpp | 52 +++++++++++++++++++ src/hotspot/share/gc/z/zRelocate.cpp | 12 ++--- .../share/gc/z/zRelocationSetSelector.cpp | 17 +++--- .../share/gc/z/zRelocationSetSelector.hpp | 10 ++-- .../gc/z/zRelocationSetSelector.inline.hpp | 24 ++++----- src/hotspot/share/gc/z/zStat.cpp | 18 +++---- src/hotspot/share/gc/z/z_globals.hpp | 2 +- src/hotspot/share/utilities/enumIterator.hpp | 27 ++++++++-- test/hotspot/gtest/gc/z/test_zPageAge.cpp | 47 +++++++++++++++++ 14 files changed, 191 insertions(+), 58 deletions(-) create mode 100644 src/hotspot/share/gc/z/zPageAge.inline.hpp create mode 100644 test/hotspot/gtest/gc/z/test_zPageAge.cpp diff --git a/src/hotspot/share/gc/z/zAllocator.cpp b/src/hotspot/share/gc/z/zAllocator.cpp index 22f3b6ba112..dd1ab3b712a 100644 --- a/src/hotspot/share/gc/z/zAllocator.cpp +++ b/src/hotspot/share/gc/z/zAllocator.cpp @@ -23,6 +23,7 @@ #include "gc/z/zAllocator.hpp" #include "gc/z/zObjectAllocator.hpp" +#include "gc/z/zPageAge.inline.hpp" ZAllocatorEden* ZAllocator::_eden; ZAllocatorForRelocation* ZAllocator::_relocation[ZAllocator::_relocation_allocators]; @@ -47,7 +48,7 @@ ZPageAge ZAllocatorForRelocation::install() { for (uint i = 0; i < ZAllocator::_relocation_allocators; ++i) { if (_relocation[i] == nullptr) { _relocation[i] = this; - return static_cast(i + 1); + return to_zpageage(i + 1); } } diff --git a/src/hotspot/share/gc/z/zAllocator.hpp b/src/hotspot/share/gc/z/zAllocator.hpp index 45a70888f9d..ec4c0ec1c9c 100644 --- a/src/hotspot/share/gc/z/zAllocator.hpp +++ b/src/hotspot/share/gc/z/zAllocator.hpp @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,7 @@ class ZPage; class ZAllocator { public: - static constexpr uint _relocation_allocators = static_cast(ZPageAge::old); + static constexpr uint _relocation_allocators = ZPageAgeCount - 1; protected: ZObjectAllocator _object_allocator; diff --git a/src/hotspot/share/gc/z/zAllocator.inline.hpp b/src/hotspot/share/gc/z/zAllocator.inline.hpp index ba558a1b0f3..ec64676dbf0 100644 --- a/src/hotspot/share/gc/z/zAllocator.inline.hpp +++ b/src/hotspot/share/gc/z/zAllocator.inline.hpp @@ -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. * * 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/zHeap.hpp" +#include "gc/z/zPageAge.inline.hpp" inline ZAllocatorEden* ZAllocator::eden() { return _eden; } inline ZAllocatorForRelocation* ZAllocator::relocation(ZPageAge page_age) { - return _relocation[static_cast(page_age) - 1]; + return _relocation[untype(page_age - 1)]; } inline ZAllocatorForRelocation* ZAllocator::old() { diff --git a/src/hotspot/share/gc/z/zGeneration.cpp b/src/hotspot/share/gc/z/zGeneration.cpp index 772c5a0a98b..534f0195c90 100644 --- a/src/hotspot/share/gc/z/zGeneration.cpp +++ b/src/hotspot/share/gc/z/zGeneration.cpp @@ -41,6 +41,7 @@ #include "gc/z/zHeap.inline.hpp" #include "gc/z/zJNICritical.hpp" #include "gc/z/zMark.inline.hpp" +#include "gc/z/zPageAge.inline.hpp" #include "gc/z/zPageAllocator.hpp" #include "gc/z/zRelocationSet.inline.hpp" #include "gc/z/zRelocationSetSelector.inline.hpp" @@ -699,11 +700,10 @@ uint ZGenerationYoung::compute_tenuring_threshold(ZRelocationSetSelectorStats st uint last_populated_age = 0; size_t last_populated_live = 0; - for (uint i = 0; i <= ZPageAgeMax; ++i) { - const ZPageAge age = static_cast(i); + for (ZPageAge age : ZPageAgeRange()) { const size_t young_live = stats.small(age).live() + stats.medium(age).live() + stats.large(age).live(); if (young_live > 0) { - last_populated_age = i; + last_populated_age = untype(age); last_populated_live = young_live; if (young_live_last > 0) { young_life_expectancy_sum += double(young_live) / double(young_live_last); @@ -842,8 +842,8 @@ void ZGenerationYoung::mark_start() { // Retire allocating pages ZAllocator::eden()->retire_pages(); - for (ZPageAge i = ZPageAge::survivor1; i <= ZPageAge::survivor14; i = static_cast(static_cast(i) + 1)) { - ZAllocator::relocation(i)->retire_pages(); + for (ZPageAge age : ZPageAgeRangeSurvivor) { + ZAllocator::relocation(age)->retire_pages(); } // Reset allocated/reclaimed/used statistics diff --git a/src/hotspot/share/gc/z/zPageAge.hpp b/src/hotspot/share/gc/z/zPageAge.hpp index b7b1688b830..3209790c008 100644 --- a/src/hotspot/share/gc/z/zPageAge.hpp +++ b/src/hotspot/share/gc/z/zPageAge.hpp @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ #ifndef SHARE_GC_Z_ZPAGEAGE_HPP #define SHARE_GC_Z_ZPAGEAGE_HPP +#include "utilities/enumIterator.hpp" #include "utilities/globalDefinitions.hpp" enum class ZPageAge : uint8_t { @@ -45,6 +46,19 @@ enum class ZPageAge : uint8_t { old }; -constexpr uint ZPageAgeMax = static_cast(ZPageAge::old); +constexpr uint ZPageAgeCount = static_cast(ZPageAge::old) + 1; +constexpr ZPageAge ZPageAgeLastPlusOne = static_cast(ZPageAgeCount); + +ENUMERATOR_RANGE(ZPageAge, + ZPageAge::eden, + ZPageAge::old); + +using ZPageAgeRange = EnumRange; + +constexpr ZPageAgeRange ZPageAgeRangeEden = ZPageAgeRange::create(); +constexpr ZPageAgeRange ZPageAgeRangeYoung = ZPageAgeRange::create(); +constexpr ZPageAgeRange ZPageAgeRangeSurvivor = ZPageAgeRange::create(); +constexpr ZPageAgeRange ZPageAgeRangeRelocation = ZPageAgeRange::create(); +constexpr ZPageAgeRange ZPageAgeRangeOld = ZPageAgeRange::create(); #endif // SHARE_GC_Z_ZPAGEAGE_HPP diff --git a/src/hotspot/share/gc/z/zPageAge.inline.hpp b/src/hotspot/share/gc/z/zPageAge.inline.hpp new file mode 100644 index 00000000000..0944caa69a6 --- /dev/null +++ b/src/hotspot/share/gc/z/zPageAge.inline.hpp @@ -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 + +inline uint untype(ZPageAge age) { + return static_cast(age); +} + +inline ZPageAge to_zpageage(uint age) { + assert(age < ZPageAgeCount, "Invalid age"); + return static_cast(age); +} + +inline ZPageAge operator+(ZPageAge age, size_t size) { + const auto size_value = checked_cast>(size); + return to_zpageage(untype(age) + size_value); +} + +inline ZPageAge operator-(ZPageAge age, size_t size) { + const auto size_value = checked_cast>(size); + return to_zpageage(untype(age) - size_value); +} + +#endif // SHARE_GC_Z_ZPAGEAGE_INLINE_HPP diff --git a/src/hotspot/share/gc/z/zRelocate.cpp b/src/hotspot/share/gc/z/zRelocate.cpp index df2dd8a01cb..b45d8b70e72 100644 --- a/src/hotspot/share/gc/z/zRelocate.cpp +++ b/src/hotspot/share/gc/z/zRelocate.cpp @@ -488,11 +488,11 @@ public: } ZPage* shared(ZPageAge age) { - return _shared[static_cast(age) - 1]; + return _shared[untype(age - 1)]; } void set_shared(ZPageAge age, ZPage* page) { - _shared[static_cast(age) - 1] = page; + _shared[untype(age - 1)] = page; } ZPage* alloc_and_retire_target_page(ZForwarding* forwarding, ZPage* target) { @@ -570,11 +570,11 @@ private: ZPage* target(ZPageAge age) { - return _target[static_cast(age) - 1]; + return _target[untype(age - 1)]; } void set_target(ZPageAge age, ZPage* page) { - _target[static_cast(age) - 1] = page; + _target[untype(age - 1)] = page; } size_t object_alignment() const { @@ -1232,12 +1232,12 @@ ZPageAge ZRelocate::compute_to_age(ZPageAge from_age) { return ZPageAge::old; } - const uint age = static_cast(from_age); + const uint age = untype(from_age); if (age >= ZGeneration::young()->tenuring_threshold()) { return ZPageAge::old; } - return static_cast(age + 1); + return to_zpageage(age + 1); } class ZFlipAgePagesTask : public ZTask { diff --git a/src/hotspot/share/gc/z/zRelocationSetSelector.cpp b/src/hotspot/share/gc/z/zRelocationSetSelector.cpp index e9ef66a19dc..aac4fd51271 100644 --- a/src/hotspot/share/gc/z/zRelocationSetSelector.cpp +++ b/src/hotspot/share/gc/z/zRelocationSetSelector.cpp @@ -25,6 +25,7 @@ #include "gc/z/zArray.inline.hpp" #include "gc/z/zForwarding.inline.hpp" #include "gc/z/zPage.inline.hpp" +#include "gc/z/zPageAge.inline.hpp" #include "gc/z/zRelocationSetSelector.inline.hpp" #include "jfr/jfrEvents.hpp" #include "logging/log.hpp" @@ -117,8 +118,8 @@ void ZRelocationSetSelectorGroup::select_inner() { const int npages = _live_pages.length(); int selected_from = 0; int selected_to = 0; - size_t npages_selected[ZPageAgeMax + 1] = { 0 }; - size_t selected_live_bytes[ZPageAgeMax + 1] = { 0 }; + size_t npages_selected[ZPageAgeCount] = { 0 }; + size_t selected_live_bytes[ZPageAgeCount] = { 0 }; size_t selected_forwarding_entries = 0; size_t from_live_bytes = 0; @@ -149,8 +150,8 @@ void ZRelocationSetSelectorGroup::select_inner() { if (diff_reclaimable > _fragmentation_limit) { selected_from = from; selected_to = to; - selected_live_bytes[static_cast(page->age())] += page_live_bytes; - npages_selected[static_cast(page->age())] += 1; + selected_live_bytes[untype(page->age())] += page_live_bytes; + npages_selected[untype(page->age())] += 1; selected_forwarding_entries = from_forwarding_entries; } @@ -172,7 +173,7 @@ void ZRelocationSetSelectorGroup::select_inner() { _forwarding_entries = selected_forwarding_entries; // 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]._npages_selected = npages_selected[i]; } @@ -200,7 +201,7 @@ void ZRelocationSetSelectorGroup::select() { } ZRelocationSetSelectorGroupStats s{}; - for (uint i = 0; i <= ZPageAgeMax; ++i) { + for (uint i = 0; i < ZPageAgeCount; ++i) { s._npages_candidates += _stats[i].npages_candidates(); s._total += _stats[i].total(); s._empty += _stats[i].empty(); @@ -239,8 +240,8 @@ void ZRelocationSetSelector::select() { ZRelocationSetSelectorStats ZRelocationSetSelector::stats() const { ZRelocationSetSelectorStats stats; - for (uint i = 0; i <= ZPageAgeMax; ++i) { - const ZPageAge age = static_cast(i); + for (ZPageAge age : ZPageAgeRange()) { + const uint i = untype(age); stats._small[i] = _small.stats(age); stats._medium[i] = _medium.stats(age); stats._large[i] = _large.stats(age); diff --git a/src/hotspot/share/gc/z/zRelocationSetSelector.hpp b/src/hotspot/share/gc/z/zRelocationSetSelector.hpp index b6ec2347153..21772405f25 100644 --- a/src/hotspot/share/gc/z/zRelocationSetSelector.hpp +++ b/src/hotspot/share/gc/z/zRelocationSetSelector.hpp @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -62,9 +62,9 @@ class ZRelocationSetSelectorStats { friend class ZRelocationSetSelector; private: - ZRelocationSetSelectorGroupStats _small[ZPageAgeMax + 1]; - ZRelocationSetSelectorGroupStats _medium[ZPageAgeMax + 1]; - ZRelocationSetSelectorGroupStats _large[ZPageAgeMax + 1]; + ZRelocationSetSelectorGroupStats _small[ZPageAgeCount]; + ZRelocationSetSelectorGroupStats _medium[ZPageAgeCount]; + ZRelocationSetSelectorGroupStats _large[ZPageAgeCount]; size_t _has_relocatable_pages; @@ -90,7 +90,7 @@ private: ZArray _live_pages; ZArray _not_selected_pages; size_t _forwarding_entries; - ZRelocationSetSelectorGroupStats _stats[ZPageAgeMax + 1]; + ZRelocationSetSelectorGroupStats _stats[ZPageAgeCount]; bool is_disabled(); bool is_selectable(); diff --git a/src/hotspot/share/gc/z/zRelocationSetSelector.inline.hpp b/src/hotspot/share/gc/z/zRelocationSetSelector.inline.hpp index 7cd0a005aac..7740e0764a6 100644 --- a/src/hotspot/share/gc/z/zRelocationSetSelector.inline.hpp +++ b/src/hotspot/share/gc/z/zRelocationSetSelector.inline.hpp @@ -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. * * 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/zGlobals.hpp" #include "gc/z/zPage.inline.hpp" +#include "gc/z/zPageAge.inline.hpp" #include "utilities/powerOfTwo.hpp" 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 { - return _small[static_cast(age)]; + return _small[untype(age)]; } inline const ZRelocationSetSelectorGroupStats& ZRelocationSetSelectorStats::medium(ZPageAge age) const { - return _medium[static_cast(age)]; + return _medium[untype(age)]; } inline const ZRelocationSetSelectorGroupStats& ZRelocationSetSelectorStats::large(ZPageAge age) const { - return _large[static_cast(age)]; + return _large[untype(age)]; } 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 uint age = static_cast(page->age()); + const uint age = untype(page->age()); _stats[age]._npages_candidates++; _stats[age]._total += size; _stats[age]._live += live; @@ -122,7 +123,7 @@ inline void ZRelocationSetSelectorGroup::register_live_page(ZPage* page) { inline void ZRelocationSetSelectorGroup::register_empty_page(ZPage* page) { const size_t size = page->size(); - const uint age = static_cast(page->age()); + const uint age = untype(page->age()); _stats[age]._npages_candidates++; _stats[age]._total += size; _stats[age]._empty += size; @@ -141,7 +142,7 @@ inline size_t ZRelocationSetSelectorGroup::forwarding_entries() const { } inline const ZRelocationSetSelectorGroupStats& ZRelocationSetSelectorGroup::stats(ZPageAge age) const { - return _stats[static_cast(age)]; + return _stats[untype(age)]; } inline void ZRelocationSetSelector::register_live_page(ZPage* page) { @@ -188,8 +189,7 @@ inline void ZRelocationSetSelector::clear_empty_pages() { inline size_t ZRelocationSetSelector::total() const { size_t sum = 0; - for (uint i = 0; i <= ZPageAgeMax; ++i) { - const ZPageAge age = static_cast(i); + for (ZPageAge age : ZPageAgeRange()) { sum += _small.stats(age).total() + _medium.stats(age).total() + _large.stats(age).total(); } return sum; @@ -197,8 +197,7 @@ inline size_t ZRelocationSetSelector::total() const { inline size_t ZRelocationSetSelector::empty() const { size_t sum = 0; - for (uint i = 0; i <= ZPageAgeMax; ++i) { - const ZPageAge age = static_cast(i); + for (ZPageAge age : ZPageAgeRange()) { sum += _small.stats(age).empty() + _medium.stats(age).empty() + _large.stats(age).empty(); } return sum; @@ -206,8 +205,7 @@ inline size_t ZRelocationSetSelector::empty() const { inline size_t ZRelocationSetSelector::relocate() const { size_t sum = 0; - for (uint i = 0; i <= ZPageAgeMax; ++i) { - const ZPageAge age = static_cast(i); + for (ZPageAge age : ZPageAgeRange()) { sum += _small.stats(age).relocate() + _medium.stats(age).relocate() + _large.stats(age).relocate(); } return sum; diff --git a/src/hotspot/share/gc/z/zStat.cpp b/src/hotspot/share/gc/z/zStat.cpp index ec751cbb693..bfde904c1e7 100644 --- a/src/hotspot/share/gc/z/zStat.cpp +++ b/src/hotspot/share/gc/z/zStat.cpp @@ -30,6 +30,7 @@ #include "gc/z/zGeneration.inline.hpp" #include "gc/z/zGlobals.hpp" #include "gc/z/zNMethodTable.hpp" +#include "gc/z/zPageAge.inline.hpp" #include "gc/z/zPageAllocator.inline.hpp" #include "gc/z/zRelocationSetSelector.inline.hpp" #include "gc/z/zStat.hpp" @@ -1499,9 +1500,7 @@ void ZStatRelocation::print_page_summary() { summary.relocate += stats.relocate(); }; - for (uint i = 0; i <= ZPageAgeMax; ++i) { - const ZPageAge age = static_cast(i); - + for (ZPageAge age : ZPageAgeRange()) { account_page_size(small_summary, _selector_stats.small(age)); account_page_size(medium_summary, _selector_stats.medium(age)); account_page_size(large_summary, _selector_stats.large(age)); @@ -1557,13 +1556,13 @@ void ZStatRelocation::print_age_table() { .center("Large") .end()); - size_t live[ZPageAgeMax + 1] = {}; - size_t total[ZPageAgeMax + 1] = {}; + size_t live[ZPageAgeCount] = {}; + size_t total[ZPageAgeCount] = {}; uint oldest_none_empty_age = 0; - for (uint i = 0; i <= ZPageAgeMax; ++i) { - ZPageAge age = static_cast(i); + for (ZPageAge age : ZPageAgeRange()) { + uint i = untype(age); auto summarize_pages = [&](const ZRelocationSetSelectorGroupStats& stats) { live[i] += stats.live(); total[i] += stats.total(); @@ -1579,7 +1578,7 @@ void ZStatRelocation::print_age_table() { } for (uint i = 0; i <= oldest_none_empty_age; ++i) { - ZPageAge age = static_cast(i); + ZPageAge age = to_zpageage(i); FormatBuffer<> age_str(""); if (age == ZPageAge::eden) { @@ -1791,8 +1790,7 @@ void ZStatHeap::at_select_relocation_set(const ZRelocationSetSelectorStats& stat ZLocker locker(&_stat_lock); size_t live = 0; - for (uint i = 0; i <= ZPageAgeMax; ++i) { - const ZPageAge age = static_cast(i); + for (ZPageAge age : ZPageAgeRange()) { live += stats.small(age).live() + stats.medium(age).live() + stats.large(age).live(); } _at_mark_end.live = live; diff --git a/src/hotspot/share/gc/z/z_globals.hpp b/src/hotspot/share/gc/z/z_globals.hpp index e1f525e5372..d818cf9fc3f 100644 --- a/src/hotspot/share/gc/z/z_globals.hpp +++ b/src/hotspot/share/gc/z/z_globals.hpp @@ -113,7 +113,7 @@ \ product(int, ZTenuringThreshold, -1, DIAGNOSTIC, \ "Young generation tenuring threshold, -1 for dynamic computation")\ - range(-1, static_cast(ZPageAgeMax)) \ + range(-1, static_cast(ZPageAgeCount) - 1) \ \ develop(bool, ZVerifyOops, false, \ "Verify accessed oops") \ diff --git a/src/hotspot/share/utilities/enumIterator.hpp b/src/hotspot/share/utilities/enumIterator.hpp index 6fa7f071f4a..42cc405fcd7 100644 --- a/src/hotspot/share/utilities/enumIterator.hpp +++ b/src/hotspot/share/utilities/enumIterator.hpp @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -25,13 +25,14 @@ #ifndef SHARE_UTILITIES_ENUMITERATOR_HPP #define SHARE_UTILITIES_ENUMITERATOR_HPP -#include -#include #include "memory/allStatic.hpp" #include "metaprogramming/enableIf.hpp" #include "metaprogramming/primitiveConversions.hpp" #include "utilities/debug.hpp" +#include +#include + // Iteration support for enums. // // E is enum type, U is underlying type of E. @@ -147,6 +148,12 @@ public: assert(value <= end, "out of range"); } + template + static constexpr void assert_in_range() { + static_assert(_start <= static_cast(Value), "out of range"); + static_assert(static_cast(Value) <= _end, "out of range"); + } + // Convert an enumerator value to the corresponding underlying type. static constexpr Underlying underlying_value(T value) { return static_cast(value); @@ -229,6 +236,12 @@ class EnumRange { 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: using EnumType = T; using Iterator = EnumIterator; @@ -252,6 +265,14 @@ public: assert(start <= end, "invalid range"); } + template + static constexpr EnumRange create() { + Traits::template assert_in_range(); + Traits::template assert_in_range(); + static_assert(Start <= End, "invalid range"); + return EnumRange(Start, End, ConstExprConstructTag{}); + } + // Return an iterator for the start of the range. constexpr Iterator begin() const { return Iterator(Traits::enumerator(_start)); diff --git a/test/hotspot/gtest/gc/z/test_zPageAge.cpp b/test/hotspot/gtest/gc/z/test_zPageAge.cpp new file mode 100644 index 00000000000..1c93a380db7 --- /dev/null +++ b/test/hotspot/gtest/gc/z/test_zPageAge.cpp @@ -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); +}