8332683: G1: G1CardSetArray::EntryDataType [2] triggers ubsan runtime errors

Reviewed-by: tschatzl, ayang
This commit is contained in:
Ivan Walulya 2024-05-27 11:21:31 +00:00
parent f3d6fbf52e
commit 891d5aedf1
2 changed files with 35 additions and 8 deletions

View File

@ -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);

View File

@ -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<EntryDataType>(card_in_region);
*entry_addr(0) = checked_cast<EntryDataType>(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<const char*>(this) + header_size_in_bytes();
return reinterpret_cast<EntryDataType const*>(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<EntryDataType*>(const_cast<const G1CardSetArray*>(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<EntryDataType>(card_idx);
*entry_addr(num_entries) = checked_cast<EntryDataType>(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 <class CardVisitor>
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));
}
}