Skip to content

Commit ffe7991

Browse files
committed
[clang] Allocate Module instances in BumpPtrAllocator (llvm#112795)
In `clang-scan-deps`, we're creating lots of `Module` instances. Allocating them all in a bump-pointer allocator reduces the number of retired instructions by 1-1.5% on my workload. (cherry picked from commit 8bbd079)
1 parent 4824a88 commit ffe7991

File tree

6 files changed

+70
-60
lines changed

6 files changed

+70
-60
lines changed

clang/include/clang/Basic/Module.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ namespace clang {
4848

4949
class FileManager;
5050
class LangOptions;
51+
class ModuleMap;
5152
class TargetInfo;
5253

5354
/// Describes the name of a module.
@@ -99,6 +100,15 @@ struct ASTFileSignature : std::array<uint8_t, 20> {
99100
}
100101
};
101102

103+
/// Required to construct a Module.
104+
///
105+
/// This tag type is only constructible by ModuleMap, guaranteeing it ownership
106+
/// of all Module instances.
107+
class ModuleConstructorTag {
108+
explicit ModuleConstructorTag() = default;
109+
friend ModuleMap;
110+
};
111+
102112
/// Describes a module or submodule.
103113
///
104114
/// Aligned to 8 bytes to allow for llvm::PointerIntPair<Module *, 3>.
@@ -514,8 +524,9 @@ class alignas(8) Module {
514524
std::vector<Conflict> Conflicts;
515525

516526
/// Construct a new module or submodule.
517-
Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
518-
bool IsFramework, bool IsExplicit, unsigned VisibilityID);
527+
Module(ModuleConstructorTag, StringRef Name, SourceLocation DefinitionLoc,
528+
Module *Parent, bool IsFramework, bool IsExplicit,
529+
unsigned VisibilityID);
519530

520531
~Module();
521532

@@ -775,7 +786,6 @@ class alignas(8) Module {
775786
///
776787
/// \returns The submodule if found, or NULL otherwise.
777788
Module *findSubmodule(StringRef Name) const;
778-
Module *findOrInferSubmodule(StringRef Name);
779789

780790
/// Get the Global Module Fragment (sub-module) for this module, it there is
781791
/// one.

clang/include/clang/Lex/ModuleMap.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,12 @@ class ModuleMap {
101101
/// named LangOpts::CurrentModule, if we've loaded it).
102102
Module *SourceModule = nullptr;
103103

104+
/// The allocator for all (sub)modules.
105+
llvm::SpecificBumpPtrAllocator<Module> ModulesAlloc;
106+
104107
/// Submodules of the current module that have not yet been attached to it.
105-
/// (Ownership is transferred if/when we create an enclosing module.)
106-
llvm::SmallVector<std::unique_ptr<Module>, 8> PendingSubmodules;
108+
/// (Relationship is set up if/when we create an enclosing module.)
109+
llvm::SmallVector<Module *, 8> PendingSubmodules;
107110

108111
/// The top-level modules that are known.
109112
llvm::StringMap<Module *> Modules;
@@ -513,6 +516,8 @@ class ModuleMap {
513516
/// \returns The named module, if known; otherwise, returns null.
514517
Module *findModule(StringRef Name) const;
515518

519+
Module *findOrInferSubmodule(Module *Parent, StringRef Name);
520+
516521
/// Retrieve a module with the given name using lexical name lookup,
517522
/// starting at the given context.
518523
///

clang/lib/Basic/Module.cpp

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@
3434

3535
using namespace clang;
3636

37-
Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
38-
bool IsFramework, bool IsExplicit, unsigned VisibilityID)
37+
Module::Module(ModuleConstructorTag, StringRef Name,
38+
SourceLocation DefinitionLoc, Module *Parent, bool IsFramework,
39+
bool IsExplicit, unsigned VisibilityID)
3940
: Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent),
4041
VisibilityID(VisibilityID), IsUnimportable(false),
4142
HasIncompatibleModuleFile(false), IsAvailable(true),
@@ -64,11 +65,7 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
6465
}
6566
}
6667

67-
Module::~Module() {
68-
for (auto *Submodule : SubModules) {
69-
delete Submodule;
70-
}
71-
}
68+
Module::~Module() = default;
7269

7370
static bool isPlatformEnvironment(const TargetInfo &Target, StringRef Feature) {
7471
StringRef Platform = Target.getPlatformName();
@@ -368,21 +365,6 @@ Module *Module::findSubmodule(StringRef Name) const {
368365
return SubModules[Pos->getValue()];
369366
}
370367

371-
Module *Module::findOrInferSubmodule(StringRef Name) {
372-
llvm::StringMap<unsigned>::const_iterator Pos = SubModuleIndex.find(Name);
373-
if (Pos != SubModuleIndex.end())
374-
return SubModules[Pos->getValue()];
375-
if (!InferSubmodules)
376-
return nullptr;
377-
Module *Result = new Module(Name, SourceLocation(), this, false, InferExplicitSubmodules, 0);
378-
Result->InferExplicitSubmodules = InferExplicitSubmodules;
379-
Result->InferSubmodules = InferSubmodules;
380-
Result->InferExportWildcard = InferExportWildcard;
381-
if (Result->InferExportWildcard)
382-
Result->Exports.push_back(Module::ExportDecl(nullptr, true));
383-
return Result;
384-
}
385-
386368
Module *Module::getGlobalModuleFragment() const {
387369
assert(isNamedModuleUnit() && "We should only query the global module "
388370
"fragment from the C++20 Named modules");

clang/lib/Frontend/IncludeTreePPActions.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ class IncludeTreePPActions final : public PPCachedActions {
135135
return reportError(FilenameBlob.takeError());
136136

137137
SourceManager &SM = PP.getSourceManager();
138+
ModuleMap &MMap = PP.getHeaderSearchInfo().getModuleMap();
138139
Expected<FileEntryRef> FE =
139140
SM.getFileManager().getFileRef(FilenameBlob->getData(),
140141
/*OpenFile=*/true);
@@ -160,14 +161,13 @@ class IncludeTreePPActions final : public PPCachedActions {
160161
return reportErrorTwine(llvm::Twine("failed to find module '") +
161162
ModuleComponents[0] + "'");
162163
for (StringRef Sub : ArrayRef(ModuleComponents).drop_front()) {
163-
M = M->findOrInferSubmodule(Sub);
164+
M = MMap.findOrInferSubmodule(M, Sub);
164165
if (!M)
165166
return reportErrorTwine(
166167
llvm::Twine("failed to find or infer submodule '") + Sub + "'");
167168
}
168169

169170
// Add to known headers for the module.
170-
ModuleMap &MMap = PP.getHeaderSearchInfo().getModuleMap();
171171
Module::Header H{"", "", *FE};
172172
MMap.addHeader(M, std::move(H), ModuleMap::NormalHeader);
173173
}

clang/lib/Lex/ModuleMap.cpp

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -362,12 +362,7 @@ ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
362362
MMapLangOpts.LineComment = true;
363363
}
364364

365-
ModuleMap::~ModuleMap() {
366-
for (auto &M : Modules)
367-
delete M.getValue();
368-
for (auto *M : ShadowModules)
369-
delete M;
370-
}
365+
ModuleMap::~ModuleMap() = default;
371366

372367
void ModuleMap::setTarget(const TargetInfo &Target) {
373368
assert((!this->Target || this->Target == &Target) &&
@@ -840,6 +835,22 @@ Module *ModuleMap::findModule(StringRef Name) const {
840835
return nullptr;
841836
}
842837

838+
Module *ModuleMap::findOrInferSubmodule(Module *Parent, StringRef Name) {
839+
if (Module *SubM = Parent->findSubmodule(Name))
840+
return SubM;
841+
if (!Parent->InferSubmodules)
842+
return nullptr;
843+
Module *Result = new (ModulesAlloc.Allocate())
844+
Module(ModuleConstructorTag{}, Name, SourceLocation(), Parent, false,
845+
Parent->InferExplicitSubmodules, 0);
846+
Result->InferExplicitSubmodules = Parent->InferExplicitSubmodules;
847+
Result->InferSubmodules = Parent->InferSubmodules;
848+
Result->InferExportWildcard = Parent->InferExportWildcard;
849+
if (Result->InferExportWildcard)
850+
Result->Exports.push_back(Module::ExportDecl(nullptr, true));
851+
return Result;
852+
}
853+
843854
Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
844855
Module *Context) const {
845856
for(; Context; Context = Context->Parent) {
@@ -866,8 +877,9 @@ std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
866877
return std::make_pair(Sub, false);
867878

868879
// Create a new module with this name.
869-
Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
870-
IsExplicit, NumCreatedModules++);
880+
Module *Result = new (ModulesAlloc.Allocate())
881+
Module(ModuleConstructorTag{}, Name, SourceLocation(), Parent,
882+
IsFramework, IsExplicit, NumCreatedModules++);
871883
if (!Parent) {
872884
if (LangOpts.CurrentModule == Name)
873885
SourceModule = Result;
@@ -879,8 +891,9 @@ std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
879891

880892
Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
881893
Module *Parent) {
882-
auto *Result = new Module("<global>", Loc, Parent, /*IsFramework*/ false,
883-
/*IsExplicit*/ true, NumCreatedModules++);
894+
auto *Result = new (ModulesAlloc.Allocate()) Module(
895+
ModuleConstructorTag{}, "<global>", Loc, Parent, /*IsFramework=*/false,
896+
/*IsExplicit=*/true, NumCreatedModules++);
884897
Result->Kind = Module::ExplicitGlobalModuleFragment;
885898
// If the created module isn't owned by a parent, send it to PendingSubmodules
886899
// to wait for its parent.
@@ -897,35 +910,33 @@ ModuleMap::createImplicitGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
897910
// Note: Here the `IsExplicit` parameter refers to the semantics in clang
898911
// modules. All the non-explicit submodules in clang modules will be exported
899912
// too. Here we simplify the implementation by using the concept.
900-
auto *Result =
901-
new Module("<implicit global>", Loc, Parent, /*IsFramework=*/false,
902-
/*IsExplicit=*/false, NumCreatedModules++);
913+
auto *Result = new (ModulesAlloc.Allocate())
914+
Module(ModuleConstructorTag{}, "<implicit global>", Loc, Parent,
915+
/*IsFramework=*/false, /*IsExplicit=*/false, NumCreatedModules++);
903916
Result->Kind = Module::ImplicitGlobalModuleFragment;
904917
return Result;
905918
}
906919

907920
Module *
908921
ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
909922
SourceLocation Loc) {
910-
auto *Result =
911-
new Module("<private>", Loc, Parent, /*IsFramework*/ false,
912-
/*IsExplicit*/ true, NumCreatedModules++);
923+
auto *Result = new (ModulesAlloc.Allocate()) Module(
924+
ModuleConstructorTag{}, "<private>", Loc, Parent, /*IsFramework=*/false,
925+
/*IsExplicit=*/true, NumCreatedModules++);
913926
Result->Kind = Module::PrivateModuleFragment;
914927
return Result;
915928
}
916929

917930
Module *ModuleMap::createModuleUnitWithKind(SourceLocation Loc, StringRef Name,
918931
Module::ModuleKind Kind) {
919-
auto *Result =
920-
new Module(Name, Loc, nullptr, /*IsFramework*/ false,
921-
/*IsExplicit*/ false, NumCreatedModules++);
932+
auto *Result = new (ModulesAlloc.Allocate())
933+
Module(ModuleConstructorTag{}, Name, Loc, nullptr, /*IsFramework=*/false,
934+
/*IsExplicit=*/false, NumCreatedModules++);
922935
Result->Kind = Kind;
923936

924937
// Reparent any current global module fragment as a submodule of this module.
925-
for (auto &Submodule : PendingSubmodules) {
938+
for (auto &Submodule : PendingSubmodules)
926939
Submodule->setParent(Result);
927-
Submodule.release(); // now owned by parent
928-
}
929940
PendingSubmodules.clear();
930941
return Result;
931942
}
@@ -977,8 +988,9 @@ Module *ModuleMap::createHeaderUnit(SourceLocation Loc, StringRef Name,
977988
assert(LangOpts.CurrentModule == Name && "module name mismatch");
978989
assert(!Modules[Name] && "redefining existing module");
979990

980-
auto *Result = new Module(Name, Loc, nullptr, /*IsFramework*/ false,
981-
/*IsExplicit*/ false, NumCreatedModules++);
991+
auto *Result = new (ModulesAlloc.Allocate())
992+
Module(ModuleConstructorTag{}, Name, Loc, nullptr, /*IsFramework=*/false,
993+
/*IsExplicit=*/false, NumCreatedModules++);
982994
Result->Kind = Module::ModuleHeaderUnit;
983995
Modules[Name] = SourceModule = Result;
984996
addHeader(Result, H, NormalHeader);
@@ -1091,9 +1103,9 @@ Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,
10911103
if (!UmbrellaHeader)
10921104
return nullptr;
10931105

1094-
Module *Result = new Module(ModuleName, SourceLocation(), Parent,
1095-
/*IsFramework=*/true, /*IsExplicit=*/false,
1096-
NumCreatedModules++);
1106+
Module *Result = new (ModulesAlloc.Allocate())
1107+
Module(ModuleConstructorTag{}, ModuleName, SourceLocation(), Parent,
1108+
/*IsFramework=*/true, /*IsExplicit=*/false, NumCreatedModules++);
10971109
InferredModuleAllowedBy[Result] = ModuleMapFID;
10981110
Result->IsInferred = true;
10991111
if (!Parent) {
@@ -1181,9 +1193,9 @@ Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
11811193
Module *ShadowingModule) {
11821194

11831195
// Create a new module with this name.
1184-
Module *Result =
1185-
new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
1186-
/*IsExplicit=*/false, NumCreatedModules++);
1196+
Module *Result = new (ModulesAlloc.Allocate())
1197+
Module(ModuleConstructorTag{}, Name, SourceLocation(), /*Parent=*/nullptr,
1198+
IsFramework, /*IsExplicit=*/false, NumCreatedModules++);
11871199
Result->ShadowingModule = ShadowingModule;
11881200
Result->markUnavailable(/*Unimportable*/true);
11891201
ModuleScopeIDs[Result] = CurrentModuleScopeID;

clang/lib/Lex/Pragma.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1752,14 +1752,15 @@ struct PragmaModuleBeginHandler : public PragmaHandler {
17521752
// Find the module we're entering. We require that a module map for it
17531753
// be loaded or implicitly loadable.
17541754
auto &HSI = PP.getHeaderSearchInfo();
1755+
auto &MM = HSI.getModuleMap();
17551756
Module *M = HSI.lookupModule(Current, ModuleName.front().second);
17561757
if (!M) {
17571758
PP.Diag(ModuleName.front().second,
17581759
diag::err_pp_module_begin_no_module_map) << Current;
17591760
return;
17601761
}
17611762
for (unsigned I = 1; I != ModuleName.size(); ++I) {
1762-
auto *NewM = M->findOrInferSubmodule(ModuleName[I].first->getName());
1763+
auto *NewM = MM.findOrInferSubmodule(M, ModuleName[I].first->getName());
17631764
if (!NewM) {
17641765
PP.Diag(ModuleName[I].second, diag::err_pp_module_begin_no_submodule)
17651766
<< M->getFullModuleName() << ModuleName[I].first;

0 commit comments

Comments
 (0)