Author: Timm Baeder
Date: 2026-09-15T12:09:30+02:00
New Revision: f1450b2d298826abdff1660d0e1747935529357f

URL: 
https://github.com/llvm/llvm-project/commit/f1450b2d298826abdff1660d0e1747935529357f
DIFF: 
https://github.com/llvm/llvm-project/commit/f1450b2d298826abdff1660d0e1747935529357f.diff

LOG: [clang][bytecode] Allocate records fields and bases via Program allocator 
(#223433)

They have the same lifetime as other things in `Program`. And we know
the number of things to allocate in advance, apart from some small
overallocations with explicitly specified virtual bases.

Added: 
    

Modified: 
    clang/lib/AST/ByteCode/Disasm.cpp
    clang/lib/AST/ByteCode/Program.cpp
    clang/lib/AST/ByteCode/Record.cpp
    clang/lib/AST/ByteCode/Record.h

Removed: 
    


################################################################################
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;


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to