From 891d5aedf12e837c9a9c7cb800fb3affa7430f00 Mon Sep 17 00:00:00 2001 From: Ivan Walulya Date: Mon, 27 May 2024 11:21:31 +0000 Subject: [PATCH] 8332683: G1: G1CardSetArray::EntryDataType [2] triggers ubsan runtime errors Reviewed-by: tschatzl, ayang --- .../share/gc/g1/g1CardSetContainers.hpp | 11 ++++++- .../gc/g1/g1CardSetContainers.inline.hpp | 32 +++++++++++++++---- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1CardSetContainers.hpp b/src/hotspot/share/gc/g1/g1CardSetContainers.hpp index 261b7e5b20a..43e6c8a3bf7 100644 --- a/src/hotspot/share/gc/g1/g1CardSetContainers.hpp +++ b/src/hotspot/share/gc/g1/g1CardSetContainers.hpp @@ -163,7 +163,8 @@ public: private: EntryCountType _size; EntryCountType volatile _num_entries; - EntryDataType _data[2]; + // VLA implementation. + EntryDataType _data[1]; static const EntryCountType LockBitMask = (EntryCountType)1 << (sizeof(EntryCountType) * BitsPerByte - 1); static const EntryCountType EntryMask = LockBitMask - 1; @@ -184,6 +185,14 @@ private: Atomic::release_store(_num_entries_addr, _local_num_entries); } }; + + EntryDataType const* base_addr() const; + + EntryDataType const* entry_addr(EntryCountType index) const; + + EntryDataType* entry_addr(EntryCountType index); + + EntryDataType at(EntryCountType index) const; public: G1CardSetArray(uint const card_in_region, EntryCountType num_cards); diff --git a/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp b/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp index 330e9d63600..94ca13b0a33 100644 --- a/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp +++ b/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp @@ -145,7 +145,7 @@ inline G1CardSetArray::G1CardSetArray(uint card_in_region, EntryCountType num_ca _num_entries(1) { assert(_size > 0, "CardSetArray of size 0 not supported."); assert(_size < LockBitMask, "Only support CardSetArray of size %u or smaller.", LockBitMask - 1); - _data[0] = checked_cast(card_in_region); + *entry_addr(0) = checked_cast(card_in_region); } inline G1CardSetArray::G1CardSetArrayLocker::G1CardSetArrayLocker(EntryCountType volatile* num_entries_addr) : @@ -167,13 +167,31 @@ inline G1CardSetArray::G1CardSetArrayLocker::G1CardSetArrayLocker(EntryCountType } } +inline G1CardSetArray::EntryDataType const* G1CardSetArray::base_addr() const { + const void* ptr = reinterpret_cast(this) + header_size_in_bytes(); + return reinterpret_cast(ptr); +} + +inline G1CardSetArray::EntryDataType const* G1CardSetArray::entry_addr(EntryCountType index) const { + assert(index < _num_entries, "precondition"); + return base_addr() + index; +} + +inline G1CardSetArray::EntryDataType* G1CardSetArray::entry_addr(EntryCountType index) { + return const_cast(const_cast(this)->entry_addr(index)); +} + +inline G1CardSetArray::EntryDataType G1CardSetArray::at(EntryCountType index) const { + return *entry_addr(index); +} + inline G1AddCardResult G1CardSetArray::add(uint card_idx) { - assert(card_idx < (1u << (sizeof(_data[0]) * BitsPerByte)), + assert(card_idx < (1u << (sizeof(EntryDataType) * BitsPerByte)), "Card index %u does not fit allowed card value range.", card_idx); EntryCountType num_entries = Atomic::load_acquire(&_num_entries) & EntryMask; EntryCountType idx = 0; for (; idx < num_entries; idx++) { - if (_data[idx] == card_idx) { + if (at(idx) == card_idx) { return Found; } } @@ -186,7 +204,7 @@ inline G1AddCardResult G1CardSetArray::add(uint card_idx) { num_entries = x.num_entries(); // Look if the cards added while waiting for the lock are the same as our card. for (; idx < num_entries; idx++) { - if (_data[idx] == card_idx) { + if (at(idx) == card_idx) { return Found; } } @@ -196,7 +214,7 @@ inline G1AddCardResult G1CardSetArray::add(uint card_idx) { return Overflow; } - _data[num_entries] = checked_cast(card_idx); + *entry_addr(num_entries) = checked_cast(card_idx); x.inc_num_entries(); @@ -207,7 +225,7 @@ inline bool G1CardSetArray::contains(uint card_idx) { EntryCountType num_entries = Atomic::load_acquire(&_num_entries) & EntryMask; for (EntryCountType idx = 0; idx < num_entries; idx++) { - if (_data[idx] == card_idx) { + if (at(idx) == card_idx) { return true; } } @@ -218,7 +236,7 @@ template void G1CardSetArray::iterate(CardVisitor& found) { EntryCountType num_entries = Atomic::load_acquire(&_num_entries) & EntryMask; for (EntryCountType idx = 0; idx < num_entries; idx++) { - found(_data[idx]); + found(at(idx)); } }