Skip to content

Commit f005fe2

Browse files
committed
[ntuple] use TClass alignment info where possible
(cherry picked from commit eec1443)
1 parent 63b1147 commit f005fe2

12 files changed

Lines changed: 114 additions & 35 deletions

tree/ntuple/inc/ROOT/RField.hxx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,6 @@ private:
167167
TClass *fClass;
168168
/// Additional information kept for each entry in `fSubfields`
169169
std::vector<RSubfieldInfo> fSubfieldsInfo;
170-
std::size_t fMaxAlignment = 1;
171170

172171
/// The staging area stores inputs to I/O rules according to the offsets given by the streamer info of
173172
/// "TypeName@@Version". The area is allocated depending on I/O rules resp. the source members of the I/O rules.
@@ -222,8 +221,8 @@ public:
222221
~RClassField() override;
223222

224223
std::vector<RValue> SplitValue(const RValue &value) const final;
225-
size_t GetValueSize() const final;
226-
size_t GetAlignment() const final { return fMaxAlignment; }
224+
std::size_t GetValueSize() const final;
225+
std::size_t GetAlignment() const final;
227226
std::uint32_t GetTypeVersion() const final;
228227
std::uint32_t GetTypeChecksum() const final;
229228
/// For polymorphic classes (that declare or inherit at least one virtual method), return the expected dynamic type

tree/ntuple/inc/ROOT/RField/RFieldProxiedCollection.hxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,8 @@ public:
176176
~RProxiedCollectionField() override = default;
177177

178178
std::vector<RValue> SplitValue(const RValue &value) const final;
179-
size_t GetValueSize() const final { return fProxy->Sizeof(); }
180-
size_t GetAlignment() const final { return alignof(std::max_align_t); }
179+
std::size_t GetValueSize() const final;
180+
std::size_t GetAlignment() const final;
181181
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
182182
};
183183

tree/ntuple/inc/ROOT/RField/RFieldSTLMisc.hxx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,8 @@ public:
264264
~ROptionalField() override = default;
265265

266266
std::vector<RValue> SplitValue(const RValue &value) const final;
267-
size_t GetValueSize() const final;
268-
size_t GetAlignment() const final;
267+
std::size_t GetValueSize() const final;
268+
std::size_t GetAlignment() const final;
269269
};
270270

271271
template <typename ItemT>
@@ -313,8 +313,8 @@ public:
313313
~RUniquePtrField() override = default;
314314

315315
std::vector<RValue> SplitValue(const RValue &value) const final;
316-
size_t GetValueSize() const final { return sizeof(std::unique_ptr<char>); }
317-
size_t GetAlignment() const final { return alignof(std::unique_ptr<char>); }
316+
std::size_t GetValueSize() const final { return sizeof(std::unique_ptr<char>); }
317+
std::size_t GetAlignment() const final { return alignof(std::unique_ptr<char>); }
318318
};
319319

320320
template <typename ItemT>
@@ -363,8 +363,8 @@ public:
363363
RField &operator=(RField &&other) = default;
364364
~RField() final = default;
365365

366-
size_t GetValueSize() const final { return sizeof(std::string); }
367-
size_t GetAlignment() const final { return std::alignment_of<std::string>(); }
366+
std::size_t GetValueSize() const final { return sizeof(std::string); }
367+
std::size_t GetAlignment() const final { return alignof(std::string); }
368368
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
369369
};
370370

@@ -436,8 +436,8 @@ public:
436436
RVariantField &operator=(RVariantField &&other) = default;
437437
~RVariantField() override = default;
438438

439-
size_t GetValueSize() const final;
440-
size_t GetAlignment() const final;
439+
std::size_t GetValueSize() const final;
440+
std::size_t GetAlignment() const final;
441441
};
442442

443443
template <typename... ItemTs>

tree/ntuple/inc/ROOT/RField/RFieldSequenceContainer.hxx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,8 @@ public:
261261
CreateUntyped(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField);
262262

263263
std::vector<RValue> SplitValue(const RValue &value) const final;
264-
size_t GetValueSize() const final { return sizeof(std::vector<char>); }
265-
size_t GetAlignment() const final { return std::alignment_of<std::vector<char>>(); }
264+
std::size_t GetValueSize() const final;
265+
std::size_t GetAlignment() const final;
266266
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
267267
};
268268

@@ -315,8 +315,8 @@ public:
315315

316316
std::vector<RValue> SplitValue(const RValue &value) const final;
317317

318-
size_t GetValueSize() const final { return sizeof(std::vector<bool>); }
319-
size_t GetAlignment() const final { return std::alignment_of<std::vector<bool>>(); }
318+
std::size_t GetValueSize() const final { return sizeof(std::vector<bool>); }
319+
std::size_t GetAlignment() const final { return alignof(std::vector<bool>); }
320320
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
321321
};
322322

@@ -410,8 +410,8 @@ public:
410410
RArrayAsVectorField &operator=(RArrayAsVectorField &&other) = default;
411411
~RArrayAsVectorField() final = default;
412412

413-
size_t GetValueSize() const final { return sizeof(std::vector<char>); }
414-
size_t GetAlignment() const final { return std::alignment_of<std::vector<char>>(); }
413+
std::size_t GetValueSize() const final;
414+
std::size_t GetAlignment() const final;
415415

416416
std::vector<RFieldBase::RValue> SplitValue(const RFieldBase::RValue &value) const final;
417417
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;

tree/ntuple/inc/ROOT/RField/RFieldSoA.hxx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ class RSoAField : public RFieldBase {
6767
/// The offset of the RVec members in the SoA type in the order of subfields of the underlying record type.
6868
/// In particular, the order is not necessarily the same then the order of RVec members in the SoA class.
6969
std::vector<std::size_t> fSoAMemberOffsets;
70-
std::size_t fMaxAlignment = 1;
7170
ROOT::Internal::RColumnIndex fNWritten;
7271

7372
RSoAField(std::string_view fieldName, const RSoAField &source); ///< Used by CloneImpl
@@ -98,7 +97,7 @@ public:
9897

9998
std::vector<RValue> SplitValue(const RValue &value) const final;
10099
size_t GetValueSize() const final;
101-
size_t GetAlignment() const final { return fMaxAlignment; }
100+
size_t GetAlignment() const final;
102101
std::uint32_t GetTypeVersion() const final;
103102
std::uint32_t GetTypeChecksum() const final;
104103
/// For polymorphic classes (that declare or inherit at least one virtual method), return the expected dynamic type

tree/ntuple/inc/ROOT/RFieldBase.hxx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -624,10 +624,9 @@ public:
624624
/// correct `std::variant` or all the elements of a collection. The default implementation assumes no subvalues
625625
/// and returns an empty vector.
626626
virtual std::vector<RValue> SplitValue(const RValue &value) const;
627-
/// The number of bytes taken by a value of the appropriate type
627+
/// What sizeof(T) for this type returns
628628
virtual size_t GetValueSize() const = 0;
629-
/// As a rule of thumb, the alignment is equal to the size of the type. There are, however, various exceptions
630-
/// to this rule depending on OS and CPU architecture. So enforce the alignment to be explicitly spelled out.
629+
/// What alignof(T) for this type returns
631630
virtual size_t GetAlignment() const = 0;
632631
std::uint32_t GetTraits() const { return fTraits; }
633632
bool HasReadCallbacks() const { return !fReadCallbacks.empty(); }

tree/ntuple/src/RFieldMeta.cxx

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
// - RField<TObject>
1616
// - RVariantField
1717

18+
#include <ROOT/RAlignmentUtils.hxx>
1819
#include <ROOT/RField.hxx>
1920
#include <ROOT/RFieldBase.hxx>
2021
#include <ROOT/RFieldUtils.hxx>
@@ -117,6 +118,12 @@ TEnum *EnsureValidEnum(std::string_view enumName)
117118
return e;
118119
}
119120

121+
void EnsureValidAlignment(std::size_t align)
122+
{
123+
if (!ROOT::Internal::IsValidAlignment(align))
124+
throw ROOT::RException(R__FAIL(std::string("invalid alignment: ") + std::to_string(align)));
125+
}
126+
120127
/// Create a comma-separated list of type names from the given fields. Uses either the real type names or the
121128
/// type aliases (if there are any, otherwise the actual type name). Used to construct template argument lists
122129
/// for templated types such as std::pair<...>, std::tuple<...>, std::variant<...>.
@@ -187,8 +194,7 @@ std::string BuildMapTypeName(ROOT::RMapField::EMapType mapType, const ROOT::RFie
187194
ROOT::RClassField::RClassField(std::string_view fieldName, const RClassField &source)
188195
: ROOT::RFieldBase(fieldName, source.GetTypeName(), ROOT::ENTupleStructure::kRecord, false /* isSimple */),
189196
fClass(source.fClass),
190-
fSubfieldsInfo(source.fSubfieldsInfo),
191-
fMaxAlignment(source.fMaxAlignment)
197+
fSubfieldsInfo(source.fSubfieldsInfo)
192198
{
193199
for (const auto &f : source.GetConstSubfields()) {
194200
RFieldBase::Attach(f->Clone(f->GetFieldName()));
@@ -281,7 +287,6 @@ ROOT::RClassField::~RClassField()
281287

282288
void ROOT::RClassField::Attach(std::unique_ptr<RFieldBase> child, RSubfieldInfo info)
283289
{
284-
fMaxAlignment = std::max(fMaxAlignment, child->GetAlignment());
285290
fSubfieldsInfo.push_back(info);
286291
RFieldBase::Attach(std::move(child));
287292
}
@@ -623,11 +628,18 @@ std::vector<ROOT::RFieldBase::RValue> ROOT::RClassField::SplitValue(const RValue
623628
return result;
624629
}
625630

626-
size_t ROOT::RClassField::GetValueSize() const
631+
std::size_t ROOT::RClassField::GetValueSize() const
627632
{
628633
return fClass->GetClassSize();
629634
}
630635

636+
std::size_t ROOT::RClassField::GetAlignment() const
637+
{
638+
const auto align = fClass->GetClassAlignment();
639+
EnsureValidAlignment(align);
640+
return align;
641+
}
642+
631643
std::uint32_t ROOT::RClassField::GetTypeVersion() const
632644
{
633645
return fClass->GetClassVersion();
@@ -657,8 +669,7 @@ void ROOT::RClassField::AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) cons
657669
ROOT::Experimental::RSoAField::RSoAField(std::string_view fieldName, const RSoAField &source)
658670
: ROOT::RFieldBase(fieldName, source.GetTypeName(), ROOT::ENTupleStructure::kCollection, false /* isSimple */),
659671
fSoAClass(source.fSoAClass),
660-
fSoAMemberOffsets(source.fSoAMemberOffsets),
661-
fMaxAlignment(source.fMaxAlignment)
672+
fSoAMemberOffsets(source.fSoAMemberOffsets)
662673
{
663674
fTraits = source.GetTraits();
664675
Attach(source.fSubfields[0]->Clone(source.fSubfields[0]->GetFieldName()));
@@ -757,8 +768,6 @@ ROOT::Experimental::RSoAField::RSoAField(std::string_view fieldName, TClass *clS
757768
leftType + " vs. " + rightType + ")"));
758769
}
759770

760-
fMaxAlignment = std::max(fMaxAlignment, vecField->GetAlignment());
761-
762771
assert(itr->second < fSoAMemberOffsets.size());
763772
fSoAMemberOffsets[itr->second] = dataMember->GetOffset();
764773
nMembers++;
@@ -863,7 +872,7 @@ std::vector<ROOT::RFieldBase::RValue> ROOT::Experimental::RSoAField::SplitValue(
863872
return std::vector<RValue>();
864873
}
865874

866-
size_t ROOT::Experimental::RSoAField::GetValueSize() const
875+
std::size_t ROOT::Experimental::RSoAField::GetValueSize() const
867876
{
868877
return fSoAClass->GetClassSize();
869878
}
@@ -878,6 +887,13 @@ std::uint32_t ROOT::Experimental::RSoAField::GetTypeChecksum() const
878887
return fSoAClass->GetCheckSum();
879888
}
880889

890+
std::size_t ROOT::Experimental::RSoAField::GetAlignment() const
891+
{
892+
const auto align = fSoAClass->GetClassAlignment();
893+
EnsureValidAlignment(align);
894+
return align;
895+
}
896+
881897
const std::type_info *ROOT::Experimental::RSoAField::GetPolymorphicTypeInfo() const
882898
{
883899
// TODO(jblomer): factor out
@@ -1198,6 +1214,18 @@ std::vector<ROOT::RFieldBase::RValue> ROOT::RProxiedCollectionField::SplitValue(
11981214
return result;
11991215
}
12001216

1217+
std::size_t ROOT::RProxiedCollectionField::GetValueSize() const
1218+
{
1219+
return fProxy->Sizeof();
1220+
}
1221+
1222+
std::size_t ROOT::RProxiedCollectionField::GetAlignment() const
1223+
{
1224+
const auto align = fProxy->GetCollectionClass()->GetClassAlignment();
1225+
EnsureValidAlignment(align);
1226+
return align;
1227+
}
1228+
12011229
void ROOT::RProxiedCollectionField::AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const
12021230
{
12031231
visitor.VisitProxiedCollectionField(*this);
@@ -1405,7 +1433,9 @@ ROOT::RExtraTypeInfoDescriptor ROOT::RStreamerField::GetExtraTypeInfo() const
14051433

14061434
std::size_t ROOT::RStreamerField::GetAlignment() const
14071435
{
1408-
return std::min(alignof(std::max_align_t), GetValueSize()); // TODO(jblomer): fix me
1436+
const auto align = fClass->GetClassAlignment();
1437+
EnsureValidAlignment(align);
1438+
return align;
14091439
}
14101440

14111441
std::size_t ROOT::RStreamerField::GetValueSize() const

tree/ntuple/src/RFieldSequenceContainer.cxx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@ std::vector<ROOT::RFieldBase::RValue> SplitVector(std::shared_ptr<void> valuePtr
3030
return result;
3131
}
3232

33+
std::size_t GetSizeOfVector()
34+
{
35+
return sizeof(std::vector<char>);
36+
}
37+
38+
std::size_t GetAlignOfVector()
39+
{
40+
return alignof(std::vector<char>);
41+
}
42+
3343
} // anonymous namespace
3444

3545
ROOT::RArrayField::RArrayField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField,
@@ -648,6 +658,16 @@ std::vector<ROOT::RFieldBase::RValue> ROOT::RVectorField::SplitValue(const RValu
648658
return SplitVector(value.GetPtr<void>(), *fSubfields[0]);
649659
}
650660

661+
std::size_t ROOT::RVectorField::GetValueSize() const
662+
{
663+
return GetSizeOfVector();
664+
}
665+
666+
std::size_t ROOT::RVectorField::GetAlignment() const
667+
{
668+
return GetAlignOfVector();
669+
}
670+
651671
void ROOT::RVectorField::AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const
652672
{
653673
visitor.VisitVectorField(*this);
@@ -974,6 +994,16 @@ std::vector<ROOT::RFieldBase::RValue> ROOT::RArrayAsVectorField::SplitValue(cons
974994
return SplitVector(value.GetPtr<void>(), *fSubfields[0]);
975995
}
976996

997+
std::size_t ROOT::RArrayAsVectorField::GetValueSize() const
998+
{
999+
return GetSizeOfVector();
1000+
}
1001+
1002+
std::size_t ROOT::RArrayAsVectorField::GetAlignment() const
1003+
{
1004+
return GetAlignOfVector();
1005+
}
1006+
9771007
void ROOT::RArrayAsVectorField::AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const
9781008
{
9791009
visitor.VisitArrayAsVectorField(*this);

tree/ntuple/test/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ ROOT_STANDARD_LIBRARY_PACKAGE(CustomStruct
1111
HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/CustomStruct.hxx
1212
SOURCES CustomStruct.cxx
1313
LINKDEF CustomStructLinkDef.h
14-
DEPENDENCIES RIO)
14+
DEPENDENCIES RIO ROOTVecOps)
1515
configure_file(CustomStruct.hxx . COPYONLY)
1616
if(MSVC AND NOT CMAKE_GENERATOR MATCHES Ninja)
1717
add_custom_command(TARGET CustomStruct POST_BUILD

tree/ntuple/test/CustomStruct.hxx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,4 +478,11 @@ struct MemberWithCustomStreamer {
478478
ClassDefNV(MemberWithCustomStreamer, 2);
479479
};
480480

481+
struct AlignmentDeterminedByTransientMember {
482+
short int fA;
483+
float fTransient; ///<!
484+
};
485+
486+
struct alignas(8) AlignedAs {};
487+
481488
#endif

0 commit comments

Comments
 (0)