Skip to content

Commit 458f2f2

Browse files
committed
[ntuple] fix up vector resize for over-aligned values
1 parent 139382c commit 458f2f2

2 files changed

Lines changed: 33 additions & 3 deletions

File tree

tree/ntuple/src/RFieldSequenceContainer.cxx

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,38 @@ void ROOT::RVectorField::ResizeVector(void *vec, std::size_t nItems, std::size_t
571571
itemDeleter->operator()(typedValue->data() + (i * itemSize), true /* dtorOnly */);
572572
}
573573
}
574-
typedValue->resize(nItems * itemSize);
574+
575+
// Resize the vector with correct alignment
576+
const auto itemAlignment = itemField.GetAlignment();
577+
const auto nbytes = nItems * itemSize;
578+
if ((oldNItems >= nItems) || (itemAlignment <= sizeof(std::max_align_t))) {
579+
typedValue->resize(nbytes);
580+
} else {
581+
auto fnAlignedResize = [](auto &vecOfAlignedStorage, std::size_t targetSize) {
582+
constexpr auto valueTypeSize = sizeof(typename std::decay_t<decltype(vecOfAlignedStorage)>::value_type);
583+
constexpr auto valueTypeAlignment = alignof(typename std::decay_t<decltype(vecOfAlignedStorage)>::value_type);
584+
static_assert(valueTypeSize == valueTypeAlignment);
585+
assert(targetSize % valueTypeAlignment == 0);
586+
vecOfAlignedStorage.resize(targetSize / valueTypeSize);
587+
};
588+
589+
static_assert(sizeof(std::max_align_t) >= 8 && kMaxAlignment == 4096);
590+
// clang-format off
591+
switch (itemAlignment) {
592+
case 16: fnAlignedResize(*static_cast<std::vector<Internal::RAlignedStorage< 16>> *>(vec), nbytes); break;
593+
case 32: fnAlignedResize(*static_cast<std::vector<Internal::RAlignedStorage< 32>> *>(vec), nbytes); break;
594+
case 64: fnAlignedResize(*static_cast<std::vector<Internal::RAlignedStorage< 64>> *>(vec), nbytes); break;
595+
case 128: fnAlignedResize(*static_cast<std::vector<Internal::RAlignedStorage< 128>> *>(vec), nbytes); break;
596+
case 256: fnAlignedResize(*static_cast<std::vector<Internal::RAlignedStorage< 256>> *>(vec), nbytes); break;
597+
case 512: fnAlignedResize(*static_cast<std::vector<Internal::RAlignedStorage< 512>> *>(vec), nbytes); break;
598+
case 1024: fnAlignedResize(*static_cast<std::vector<Internal::RAlignedStorage<1024>> *>(vec), nbytes); break;
599+
case 2048: fnAlignedResize(*static_cast<std::vector<Internal::RAlignedStorage<2048>> *>(vec), nbytes); break;
600+
case 4096: fnAlignedResize(*static_cast<std::vector<Internal::RAlignedStorage<4096>> *>(vec), nbytes); break;
601+
default: R__ASSERT(false);
602+
}
603+
// clang-format on
604+
}
605+
575606
if (!(itemField.GetTraits() & kTraitTriviallyConstructible)) {
576607
for (std::size_t i = allDeallocated ? 0 : oldNItems; i < nItems; ++i) {
577608
CallConstructValueOn(itemField, typedValue->data() + (i * itemSize));

tree/ntuple/test/rfield_class.cxx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,5 @@ TEST(RNTuple, AlignmentCornerCases)
540540

541541
auto view = reader->GetView<AlignmentEnvelope>("f");
542542
EXPECT_EQ(1u, view(0).fVec.size());
543-
// TODO(jblomer): FIXME
544-
// EXPECT_EQ(0, reinterpret_cast<std::uintptr_t>(view(0).fVec.data()) % alignof(OverAligned));
543+
EXPECT_EQ(0, reinterpret_cast<std::uintptr_t>(view(0).fVec.data()) % alignof(OverAligned));
545544
}

0 commit comments

Comments
 (0)