Skip to content

Commit c616780

Browse files
committed
[clang][bytecode] Allocate Record Fields and bases via Program
Records have Program-lifetime, but we used to allocate their fields, bases and virtual bases using llvm::SmallVector. However, after creating a Record, it doesn't change and we know all the number of elements beforehand. So, allocate the lists via the BumpPtrAllocator we already have in Program. This results in slight compile-time improvements: https://llvm-compile-time-tracker.com/compare.php?from=3a3d55705b0f69f3ef5bed0b0211e7c884001842&to=e0fede973116c4d43e9883586c737c3d0bb99c3e&stat=instructions:u Unfortunately, we still have the three DenseMaps in Record, so they still heap-allocate memory on their own.
1 parent 1e3f6a6 commit c616780

File tree

3 files changed

+57
-41
lines changed

3 files changed

+57
-41
lines changed

clang/lib/AST/ByteCode/Program.cpp

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -315,9 +315,17 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
315315
};
316316

317317
// Reserve space for base classes.
318-
Record::BaseList Bases;
319-
Record::VirtualBaseList VirtBases;
318+
Record::Base *Bases = nullptr;
319+
Record::Base *VBases = nullptr;
320+
unsigned NumRecordBases = 0;
321+
unsigned NumRecordVBases = 0;
320322
if (const auto *CD = dyn_cast<CXXRecordDecl>(RD)) {
323+
unsigned NumBases = CD->getNumBases();
324+
unsigned NumVBases = CD->getNumVBases();
325+
326+
Bases = new (*this) Record::Base[NumBases];
327+
VBases = new (*this) Record::Base[NumVBases];
328+
321329
for (const CXXBaseSpecifier &Spec : CD->bases()) {
322330
if (Spec.isVirtual())
323331
continue;
@@ -334,9 +342,11 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
334342
return nullptr;
335343

336344
BaseSize += align(sizeof(InlineDescriptor));
337-
Bases.push_back({BD, BaseSize, Desc, BR});
345+
new (&Bases[NumRecordBases]) Record::Base{BD, BaseSize, Desc, BR};
338346
BaseSize += align(BR->getSize());
347+
++NumRecordBases;
339348
}
349+
assert(NumRecordBases <= NumBases);
340350

341351
for (const CXXBaseSpecifier &Spec : CD->vbases()) {
342352
const auto *RT = Spec.getType()->getAs<RecordType>();
@@ -351,13 +361,17 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
351361
return nullptr;
352362

353363
VirtSize += align(sizeof(InlineDescriptor));
354-
VirtBases.push_back({BD, VirtSize, Desc, BR});
364+
new (&VBases[NumRecordVBases]) Record::Base{BD, VirtSize, Desc, BR};
355365
VirtSize += align(BR->getSize());
366+
++NumRecordVBases;
356367
}
368+
assert(NumRecordVBases <= NumVBases);
357369
}
358370

359371
// Reserve space for fields.
360-
Record::FieldList Fields;
372+
unsigned NumFields = std::distance(RD->field_begin(), RD->field_end());
373+
unsigned NumRecordFields = 0;
374+
Record::Field *Fields = new (*this) Record::Field[NumFields];
361375
for (const FieldDecl *FD : RD->fields()) {
362376
FD = FD->getFirstDecl();
363377
// Note that we DO create fields and descriptors
@@ -382,12 +396,15 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
382396
}
383397
if (!Desc)
384398
return nullptr;
385-
Fields.push_back({FD, BaseSize, Desc});
399+
400+
new (&Fields[NumRecordFields]) Record::Field{FD, BaseSize, Desc};
386401
BaseSize += align(Desc->getAllocSize());
402+
++NumRecordFields;
387403
}
388404

389-
Record *R = new (Allocator) Record(RD, std::move(Bases), std::move(Fields),
390-
std::move(VirtBases), VirtSize, BaseSize);
405+
Record *R =
406+
new (Allocator) Record(RD, Bases, NumRecordBases, Fields, NumRecordFields,
407+
VBases, NumRecordVBases, VirtSize, BaseSize);
391408
Records[RD] = R;
392409
return R;
393410
}

clang/lib/AST/ByteCode/Record.cpp

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,23 @@
1212
using namespace clang;
1313
using namespace clang::interp;
1414

15-
Record::Record(const RecordDecl *Decl, BaseList &&SrcBases,
16-
FieldList &&SrcFields, VirtualBaseList &&SrcVirtualBases,
17-
unsigned VirtualSize, unsigned BaseSize)
18-
: Decl(Decl), Bases(std::move(SrcBases)), Fields(std::move(SrcFields)),
15+
Record::Record(const RecordDecl *Decl, const Base *SrcBases, unsigned NumBases,
16+
const Field *Fields, unsigned NumFields, Base *VBases,
17+
unsigned NumVBases, unsigned VirtualSize, unsigned BaseSize)
18+
: Decl(Decl), Bases(SrcBases), NumBases(NumBases), Fields(Fields),
19+
NumFields(NumFields), VBases(VBases), NumVBases(NumVBases),
1920
BaseSize(BaseSize), VirtualSize(VirtualSize), IsUnion(Decl->isUnion()),
2021
IsAnonymousUnion(IsUnion && Decl->isAnonymousStructOrUnion()) {
21-
for (Base &V : SrcVirtualBases)
22-
VirtualBases.push_back({V.Decl, V.Offset + BaseSize, V.Desc, V.R});
2322

24-
for (Base &B : Bases)
23+
for (unsigned I = 0; I != NumVBases; ++I) {
24+
VBases[I].Offset += BaseSize;
25+
}
26+
27+
for (const Base &B : bases())
2528
BaseMap[B.Decl] = &B;
26-
for (Field &F : Fields)
29+
for (const Field &F : fields())
2730
FieldMap[F.Decl] = &F;
28-
for (Base &V : VirtualBases)
31+
for (const Base &V : virtual_bases())
2932
VirtualBaseMap[V.Decl] = &V;
3033
}
3134

clang/lib/AST/ByteCode/Record.h

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,6 @@ class Record final {
4141
const Record *R;
4242
};
4343

44-
/// Mapping from identifiers to field descriptors.
45-
using FieldList = llvm::SmallVector<Field, 8>;
46-
/// Mapping from identifiers to base classes.
47-
using BaseList = llvm::SmallVector<Base, 8>;
48-
/// List of virtual base classes.
49-
using VirtualBaseList = llvm::SmallVector<Base, 2>;
50-
5144
public:
5245
/// Returns the underlying declaration.
5346
const RecordDecl *getDecl() const { return Decl; }
@@ -76,61 +69,64 @@ class Record final {
7669
return nullptr;
7770
}
7871

79-
using const_field_iter = FieldList::const_iterator;
72+
using const_field_iter = ArrayRef<Field>::const_iterator;
8073
llvm::iterator_range<const_field_iter> fields() const {
81-
return llvm::make_range(Fields.begin(), Fields.end());
74+
return llvm::make_range(Fields, Fields + NumFields);
8275
}
8376

84-
unsigned getNumFields() const { return Fields.size(); }
77+
unsigned getNumFields() const { return NumFields; }
8578
const Field *getField(unsigned I) const { return &Fields[I]; }
8679

87-
using const_base_iter = BaseList::const_iterator;
80+
using const_base_iter = ArrayRef<Base>::const_iterator;
8881
llvm::iterator_range<const_base_iter> bases() const {
89-
return llvm::make_range(Bases.begin(), Bases.end());
82+
return llvm::make_range(Bases, Bases + NumBases);
9083
}
9184

92-
unsigned getNumBases() const { return Bases.size(); }
85+
unsigned getNumBases() const { return NumBases; }
9386
const Base *getBase(unsigned I) const {
9487
assert(I < getNumBases());
9588
return &Bases[I];
9689
}
9790

98-
using const_virtual_iter = VirtualBaseList::const_iterator;
91+
using const_virtual_iter = ArrayRef<Base>::const_iterator;
9992
llvm::iterator_range<const_virtual_iter> virtual_bases() const {
100-
return llvm::make_range(VirtualBases.begin(), VirtualBases.end());
93+
return llvm::make_range(VBases, VBases + NumVBases);
10194
}
10295

103-
unsigned getNumVirtualBases() const { return VirtualBases.size(); }
104-
const Base *getVirtualBase(unsigned I) const { return &VirtualBases[I]; }
96+
unsigned getNumVirtualBases() const { return NumVBases; }
97+
const Base *getVirtualBase(unsigned I) const { return &VBases[I]; }
10598

10699
void dump(llvm::raw_ostream &OS, unsigned Indentation = 0,
107100
unsigned Offset = 0) const;
108101
void dump() const { dump(llvm::errs()); }
109102

110103
private:
111104
/// Constructor used by Program to create record descriptors.
112-
Record(const RecordDecl *, BaseList &&Bases, FieldList &&Fields,
113-
VirtualBaseList &&VirtualBases, unsigned VirtualSize,
114-
unsigned BaseSize);
105+
Record(const RecordDecl *, const Base *Bases, unsigned NumBases,
106+
const Field *Fields, unsigned NumFields, Base *VBases,
107+
unsigned NumVBases, unsigned VirtualSize, unsigned BaseSize);
115108

116109
private:
117110
friend class Program;
118111

119112
/// Original declaration.
120113
const RecordDecl *Decl;
121114
/// List of all base classes.
122-
BaseList Bases;
115+
const Base *Bases;
116+
unsigned NumBases;
123117
/// List of all the fields in the record.
124-
FieldList Fields;
118+
const Field *Fields;
119+
unsigned NumFields;
125120
/// List o fall virtual bases.
126-
VirtualBaseList VirtualBases;
121+
Base *VBases;
122+
unsigned NumVBases;
127123

128124
/// Mapping from declarations to bases.
129125
llvm::DenseMap<const RecordDecl *, const Base *> BaseMap;
130126
/// Mapping from field identifiers to descriptors.
131127
llvm::DenseMap<const FieldDecl *, const Field *> FieldMap;
132128
/// Mapping from declarations to virtual bases.
133-
llvm::DenseMap<const RecordDecl *, Base *> VirtualBaseMap;
129+
llvm::DenseMap<const RecordDecl *, const Base *> VirtualBaseMap;
134130
/// Size of the structure.
135131
unsigned BaseSize;
136132
/// Size of all virtual bases.

0 commit comments

Comments
 (0)