[clang] [clang][bytecode] Allocate records fields and bases via Program allocator (PR #223433)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 15 01:14:22 PDT 2026
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/223433
>From 54a785a7f7947953d7abeaffce679f62ef3c8c84 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Mon, 14 Sep 2026 14:58:21 +0200
Subject: [PATCH] record alloc
---
clang/lib/AST/ByteCode/Disasm.cpp | 9 +++---
clang/lib/AST/ByteCode/Program.cpp | 49 ++++++++++++++++++++++++------
clang/lib/AST/ByteCode/Record.cpp | 18 +++--------
clang/lib/AST/ByteCode/Record.h | 27 ++++++----------
4 files changed, 57 insertions(+), 46 deletions(-)
diff --git a/clang/lib/AST/ByteCode/Disasm.cpp b/clang/lib/AST/ByteCode/Disasm.cpp
index 03187529541d8..9ef08855cdbb7 100644
--- a/clang/lib/AST/ByteCode/Disasm.cpp
+++ b/clang/lib/AST/ByteCode/Disasm.cpp
@@ -348,11 +348,10 @@ LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const {
Bytes += DummyVariables.getMemorySize();
// All Records.
- for (const Record *R : Records.values()) {
- Bytes += sizeof(Record) + R->BaseMap.getMemorySize();
- Bytes += R->Fields.capacity_in_bytes() + R->Bases.capacity_in_bytes() +
- R->VirtualBases.capacity_in_bytes();
- }
+ // They are allocated using the program allocator, so only get the size from
+ // the BaseMap.
+ for (const Record *R : Records.values())
+ Bytes += R->BaseMap.getMemorySize();
// Globals are allocated via the allocator, so already counted.
diff --git a/clang/lib/AST/ByteCode/Program.cpp b/clang/lib/AST/ByteCode/Program.cpp
index f7bb9540570a7..6e87eeb79f738 100644
--- a/clang/lib/AST/ByteCode/Program.cpp
+++ b/clang/lib/AST/ByteCode/Program.cpp
@@ -268,12 +268,21 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
/*IsMutable=*/false, /*IsVolatile=*/false);
};
+ bool HasPtrField = false;
// Reserve space for base classes.
- Record::BaseList Bases;
- Record::VirtualBaseList VirtBases;
+ unsigned NumBases = 0;
+ Record::Base *Bases = nullptr;
+ unsigned NumVBases = 0;
+ Record::Base *VBases = nullptr;
if (const auto *CD = dyn_cast<CXXRecordDecl>(RD)) {
- Bases.reserve(CD->getNumBases());
+ NumBases = CD->getNumBases();
+ // NB: This overallocates by all explicitly specified virtual bases.
+ if (NumBases != 0)
+ Bases = Allocate<Record::Base>(NumBases);
+
+ unsigned I = 0;
for (const CXXBaseSpecifier &Spec : CD->bases()) {
+ assert(I <= NumBases);
if (Spec.isVirtual())
continue;
@@ -288,11 +297,20 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
return nullptr;
BaseSize += align(sizeof(InlineDescriptor));
- Bases.emplace_back(BD, Desc, BR, BaseSize);
+ new (&Bases[I]) Record::Base(BD, Desc, BR, BaseSize);
BaseSize += align(BR->getSize());
+ HasPtrField |= BR->hasPtrField();
+ ++I;
}
+ // Make sure we don't include the virtual base specifiers we skipped above.
+ NumBases = I;
+ I = 0;
+ NumVBases = CD->getNumVBases();
+ if (NumVBases != 0)
+ VBases = Allocate<Record::Base>(NumVBases);
for (const CXXBaseSpecifier &Spec : CD->vbases()) {
+ assert(I <= NumVBases);
const auto *BD = Spec.getType()->castAsCXXRecordDecl();
const Record *BR = getOrCreateRecord(BD);
@@ -301,15 +319,20 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
return nullptr;
VirtSize += align(sizeof(InlineDescriptor));
- VirtBases.emplace_back(BD, Desc, BR, VirtSize);
+ new (&VBases[I]) Record::Base(BD, Desc, BR, VirtSize);
VirtSize += align(BR->getSize());
+ HasPtrField |= BR->hasPtrField();
+ ++I;
}
+ assert(I == NumVBases);
}
// Reserve space for fields.
- Record::FieldList Fields;
- Fields.reserve(RD->getNumFields());
- bool HasPtrField = false;
+ unsigned NumFields = RD->getNumFields();
+ Record::Field *Fields = nullptr;
+ if (NumFields != 0)
+ Fields = Allocate<Record::Field>(NumFields);
+ unsigned I = 0;
for (const FieldDecl *FD : RD->fields()) {
FD = FD->getFirstDecl();
// Note that we DO create fields and descriptors
@@ -340,12 +363,18 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
} else {
Desc = allocateDescriptor(FD);
}
- Fields.emplace_back(FD, Desc, BaseSize, T);
+ assert(Desc);
+ new (&Fields[I]) Record::Field(FD, Desc, BaseSize, T);
BaseSize += align(Desc->getAllocSize());
+ ++I;
}
+ // Adjust virtual base offsets to account for base size.
+ for (unsigned I = 0; I != NumVBases; ++I)
+ VBases[I].Offset += BaseSize;
+
Record *R = new (Allocator)
- Record(RD, std::move(Bases), std::move(Fields), std::move(VirtBases),
+ Record(RD, {Bases, NumBases}, {Fields, NumFields}, {VBases, NumVBases},
VirtSize, BaseSize, HasPtrField);
Records[RD] = R;
return R;
diff --git a/clang/lib/AST/ByteCode/Record.cpp b/clang/lib/AST/ByteCode/Record.cpp
index 7faebda880c80..4907f142ac3c0 100644
--- a/clang/lib/AST/ByteCode/Record.cpp
+++ b/clang/lib/AST/ByteCode/Record.cpp
@@ -12,25 +12,15 @@
using namespace clang;
using namespace clang::interp;
-Record::Record(const RecordDecl *Decl, BaseList &&SrcBases,
- FieldList &&SrcFields, VirtualBaseList &&SrcVirtualBases,
+Record::Record(const RecordDecl *Decl, ArrayRef<Base> Bases,
+ ArrayRef<Field> Fields, ArrayRef<Base> VirtualBases,
unsigned VirtualSize, unsigned BaseSize, bool HasPtrField)
- : Decl(Decl), Bases(std::move(SrcBases)), Fields(std::move(SrcFields)),
+ : Decl(Decl), Bases(Bases), Fields(Fields), VirtualBases(VirtualBases),
BaseSize(BaseSize), VirtualSize(VirtualSize), IsUnion(Decl->isUnion()),
IsAnonymousUnion(IsUnion && Decl->isAnonymousStructOrUnion()),
HasPtrField(HasPtrField) {
- for (Base &V : SrcVirtualBases)
- VirtualBases.emplace_back(V.Decl, V.Desc, V.R, V.Offset + BaseSize);
-
- for (Base &B : Bases) {
+ for (const Base &B : this->Bases)
BaseMap[B.Decl] = &B;
- if (!this->HasPtrField)
- this->HasPtrField |= B.R->hasPtrField();
- }
- for (Base &V : VirtualBases) {
- if (!this->HasPtrField)
- this->HasPtrField |= V.R->hasPtrField();
- }
}
std::string Record::getName() const {
diff --git a/clang/lib/AST/ByteCode/Record.h b/clang/lib/AST/ByteCode/Record.h
index f03927bf71ffe..838643335b3b9 100644
--- a/clang/lib/AST/ByteCode/Record.h
+++ b/clang/lib/AST/ByteCode/Record.h
@@ -16,6 +16,7 @@
#include "PrimType.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "llvm/ADT/ArrayRef.h"
namespace clang {
namespace interp {
@@ -61,13 +62,6 @@ class Record final {
: Decl(D), Desc(Desc), R(R), Offset(Offset) {}
};
- /// Mapping from identifiers to field descriptors.
- using FieldList = llvm::SmallVector<Field, 8>;
- /// Mapping from identifiers to base classes.
- using BaseList = llvm::SmallVector<Base, 8>;
- /// List of virtual base classes.
- using VirtualBaseList = llvm::SmallVector<Base, 0>;
-
public:
/// Returns the underlying declaration.
const RecordDecl *getDecl() const { return Decl; }
@@ -94,7 +88,7 @@ class Record final {
/// with no destructor or for those with a trivial destructor.
bool hasTrivialDtor() const;
- using const_field_iter = FieldList::const_iterator;
+ using const_field_iter = ArrayRef<Field>::const_iterator;
llvm::iterator_range<const_field_iter> fields() const {
return llvm::make_range(Fields.begin(), Fields.end());
}
@@ -109,7 +103,7 @@ class Record final {
return &Fields[FD->getFieldIndex()];
}
- using const_base_iter = BaseList::const_iterator;
+ using const_base_iter = ArrayRef<Base>::const_iterator;
llvm::iterator_range<const_base_iter> bases() const {
return llvm::make_range(Bases.begin(), Bases.end());
}
@@ -126,8 +120,7 @@ class Record final {
const Base *getBaseOrNull(const RecordDecl *RD) const;
const Base *findBase(unsigned Offset) const;
- using const_virtual_iter = VirtualBaseList::const_iterator;
- llvm::iterator_range<const_virtual_iter> virtual_bases() const {
+ llvm::iterator_range<const_base_iter> virtual_bases() const {
return llvm::make_range(VirtualBases.begin(), VirtualBases.end());
}
@@ -142,9 +135,9 @@ class Record final {
private:
/// Constructor used by Program to create record descriptors.
- Record(const RecordDecl *, BaseList &&Bases, FieldList &&Fields,
- VirtualBaseList &&VirtualBases, unsigned VirtualSize,
- unsigned BaseSize, bool HasPtrField = true);
+ Record(const RecordDecl *, ArrayRef<Base> Bases, ArrayRef<Field> Fields,
+ ArrayRef<Base> VirtualBases, unsigned VirtualSize, unsigned BaseSize,
+ bool HasPtrField = true);
private:
friend class Program;
@@ -152,11 +145,11 @@ class Record final {
/// Original declaration.
const RecordDecl *Decl;
/// List of all base classes.
- BaseList Bases;
+ ArrayRef<Base> Bases;
/// List of all the fields in the record.
- FieldList Fields;
+ ArrayRef<Field> Fields;
/// List of all virtual bases.
- VirtualBaseList VirtualBases;
+ ArrayRef<Base> VirtualBases;
/// Mapping from declarations to bases.
llvm::DenseMap<const RecordDecl *, const Base *> BaseMap;
More information about the cfe-commits
mailing list