Skip to content

Commit 8bbd079

Browse files
authored
[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.
1 parent 40c3e58 commit 8bbd079

File tree

5 files changed

+68
-58
lines changed

5 files changed

+68
-58
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>.
@@ -497,8 +507,9 @@ class alignas(8) Module {
497507
std::vector<Conflict> Conflicts;
498508

499509
/// Construct a new module or submodule.
500-
Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
501-
bool IsFramework, bool IsExplicit, unsigned VisibilityID);
510+
Module(ModuleConstructorTag, StringRef Name, SourceLocation DefinitionLoc,
511+
Module *Parent, bool IsFramework, bool IsExplicit,
512+
unsigned VisibilityID);
502513

503514
~Module();
504515

@@ -749,7 +760,6 @@ class alignas(8) Module {
749760
///
750761
/// \returns The submodule if found, or NULL otherwise.
751762
Module *findSubmodule(StringRef Name) const;
752-
Module *findOrInferSubmodule(StringRef Name);
753763

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

clang/include/clang/Lex/ModuleMap.h

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

96+
/// The allocator for all (sub)modules.
97+
llvm::SpecificBumpPtrAllocator<Module> ModulesAlloc;
98+
9699
/// Submodules of the current module that have not yet been attached to it.
97-
/// (Ownership is transferred if/when we create an enclosing module.)
98-
llvm::SmallVector<std::unique_ptr<Module>, 8> PendingSubmodules;
100+
/// (Relationship is set up if/when we create an enclosing module.)
101+
llvm::SmallVector<Module *, 8> PendingSubmodules;
99102

100103
/// The top-level modules that are known.
101104
llvm::StringMap<Module *> Modules;
@@ -502,6 +505,8 @@ class ModuleMap {
502505
/// \returns The named module, if known; otherwise, returns null.
503506
Module *findModule(StringRef Name) const;
504507

508+
Module *findOrInferSubmodule(Module *Parent, StringRef Name);
509+
505510
/// Retrieve a module with the given name using lexical name lookup,
506511
/// starting at the given context.
507512
///

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),
@@ -58,11 +59,7 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
5859
}
5960
}
6061

61-
Module::~Module() {
62-
for (auto *Submodule : SubModules) {
63-
delete Submodule;
64-
}
65-
}
62+
Module::~Module() = default;
6663

6764
static bool isPlatformEnvironment(const TargetInfo &Target, StringRef Feature) {
6865
StringRef Platform = Target.getPlatformName();
@@ -361,21 +358,6 @@ Module *Module::findSubmodule(StringRef Name) const {
361358
return SubModules[Pos->getValue()];
362359
}
363360

364-
Module *Module::findOrInferSubmodule(StringRef Name) {
365-
llvm::StringMap<unsigned>::const_iterator Pos = SubModuleIndex.find(Name);
366-
if (Pos != SubModuleIndex.end())
367-
return SubModules[Pos->getValue()];
368-
if (!InferSubmodules)
369-
return nullptr;
370-
Module *Result = new Module(Name, SourceLocation(), this, false, InferExplicitSubmodules, 0);
371-
Result->InferExplicitSubmodules = InferExplicitSubmodules;
372-
Result->InferSubmodules = InferSubmodules;
373-
Result->InferExportWildcard = InferExportWildcard;
374-
if (Result->InferExportWildcard)
375-
Result->Exports.push_back(Module::ExportDecl(nullptr, true));
376-
return Result;
377-
}
378-
379361
Module *Module::getGlobalModuleFragment() const {
380362
assert(isNamedModuleUnit() && "We should only query the global module "
381363
"fragment from the C++20 Named modules");

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) &&
@@ -831,6 +826,22 @@ Module *ModuleMap::findModule(StringRef Name) const {
831826
return nullptr;
832827
}
833828

829+
Module *ModuleMap::findOrInferSubmodule(Module *Parent, StringRef Name) {
830+
if (Module *SubM = Parent->findSubmodule(Name))
831+
return SubM;
832+
if (!Parent->InferSubmodules)
833+
return nullptr;
834+
Module *Result = new (ModulesAlloc.Allocate())
835+
Module(ModuleConstructorTag{}, Name, SourceLocation(), Parent, false,
836+
Parent->InferExplicitSubmodules, 0);
837+
Result->InferExplicitSubmodules = Parent->InferExplicitSubmodules;
838+
Result->InferSubmodules = Parent->InferSubmodules;
839+
Result->InferExportWildcard = Parent->InferExportWildcard;
840+
if (Result->InferExportWildcard)
841+
Result->Exports.push_back(Module::ExportDecl(nullptr, true));
842+
return Result;
843+
}
844+
834845
Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
835846
Module *Context) const {
836847
for(; Context; Context = Context->Parent) {
@@ -857,8 +868,9 @@ std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
857868
return std::make_pair(Sub, false);
858869

859870
// Create a new module with this name.
860-
Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
861-
IsExplicit, NumCreatedModules++);
871+
Module *Result = new (ModulesAlloc.Allocate())
872+
Module(ModuleConstructorTag{}, Name, SourceLocation(), Parent,
873+
IsFramework, IsExplicit, NumCreatedModules++);
862874
if (!Parent) {
863875
if (LangOpts.CurrentModule == Name)
864876
SourceModule = Result;
@@ -870,8 +882,9 @@ std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
870882

871883
Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
872884
Module *Parent) {
873-
auto *Result = new Module("<global>", Loc, Parent, /*IsFramework*/ false,
874-
/*IsExplicit*/ true, NumCreatedModules++);
885+
auto *Result = new (ModulesAlloc.Allocate()) Module(
886+
ModuleConstructorTag{}, "<global>", Loc, Parent, /*IsFramework=*/false,
887+
/*IsExplicit=*/true, NumCreatedModules++);
875888
Result->Kind = Module::ExplicitGlobalModuleFragment;
876889
// If the created module isn't owned by a parent, send it to PendingSubmodules
877890
// to wait for its parent.
@@ -888,35 +901,33 @@ ModuleMap::createImplicitGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
888901
// Note: Here the `IsExplicit` parameter refers to the semantics in clang
889902
// modules. All the non-explicit submodules in clang modules will be exported
890903
// too. Here we simplify the implementation by using the concept.
891-
auto *Result =
892-
new Module("<implicit global>", Loc, Parent, /*IsFramework=*/false,
893-
/*IsExplicit=*/false, NumCreatedModules++);
904+
auto *Result = new (ModulesAlloc.Allocate())
905+
Module(ModuleConstructorTag{}, "<implicit global>", Loc, Parent,
906+
/*IsFramework=*/false, /*IsExplicit=*/false, NumCreatedModules++);
894907
Result->Kind = Module::ImplicitGlobalModuleFragment;
895908
return Result;
896909
}
897910

898911
Module *
899912
ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
900913
SourceLocation Loc) {
901-
auto *Result =
902-
new Module("<private>", Loc, Parent, /*IsFramework*/ false,
903-
/*IsExplicit*/ true, NumCreatedModules++);
914+
auto *Result = new (ModulesAlloc.Allocate()) Module(
915+
ModuleConstructorTag{}, "<private>", Loc, Parent, /*IsFramework=*/false,
916+
/*IsExplicit=*/true, NumCreatedModules++);
904917
Result->Kind = Module::PrivateModuleFragment;
905918
return Result;
906919
}
907920

908921
Module *ModuleMap::createModuleUnitWithKind(SourceLocation Loc, StringRef Name,
909922
Module::ModuleKind Kind) {
910-
auto *Result =
911-
new Module(Name, Loc, nullptr, /*IsFramework*/ false,
912-
/*IsExplicit*/ false, NumCreatedModules++);
923+
auto *Result = new (ModulesAlloc.Allocate())
924+
Module(ModuleConstructorTag{}, Name, Loc, nullptr, /*IsFramework=*/false,
925+
/*IsExplicit=*/false, NumCreatedModules++);
913926
Result->Kind = Kind;
914927

915928
// Reparent any current global module fragment as a submodule of this module.
916-
for (auto &Submodule : PendingSubmodules) {
929+
for (auto &Submodule : PendingSubmodules)
917930
Submodule->setParent(Result);
918-
Submodule.release(); // now owned by parent
919-
}
920931
PendingSubmodules.clear();
921932
return Result;
922933
}
@@ -968,8 +979,9 @@ Module *ModuleMap::createHeaderUnit(SourceLocation Loc, StringRef Name,
968979
assert(LangOpts.CurrentModule == Name && "module name mismatch");
969980
assert(!Modules[Name] && "redefining existing module");
970981

971-
auto *Result = new Module(Name, Loc, nullptr, /*IsFramework*/ false,
972-
/*IsExplicit*/ false, NumCreatedModules++);
982+
auto *Result = new (ModulesAlloc.Allocate())
983+
Module(ModuleConstructorTag{}, Name, Loc, nullptr, /*IsFramework=*/false,
984+
/*IsExplicit=*/false, NumCreatedModules++);
973985
Result->Kind = Module::ModuleHeaderUnit;
974986
Modules[Name] = SourceModule = Result;
975987
addHeader(Result, H, NormalHeader);
@@ -1082,9 +1094,9 @@ Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,
10821094
if (!UmbrellaHeader)
10831095
return nullptr;
10841096

1085-
Module *Result = new Module(ModuleName, SourceLocation(), Parent,
1086-
/*IsFramework=*/true, /*IsExplicit=*/false,
1087-
NumCreatedModules++);
1097+
Module *Result = new (ModulesAlloc.Allocate())
1098+
Module(ModuleConstructorTag{}, ModuleName, SourceLocation(), Parent,
1099+
/*IsFramework=*/true, /*IsExplicit=*/false, NumCreatedModules++);
10881100
InferredModuleAllowedBy[Result] = ModuleMapFID;
10891101
Result->IsInferred = true;
10901102
if (!Parent) {
@@ -1173,9 +1185,9 @@ Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
11731185
Module *ShadowingModule) {
11741186

11751187
// Create a new module with this name.
1176-
Module *Result =
1177-
new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
1178-
/*IsExplicit=*/false, NumCreatedModules++);
1188+
Module *Result = new (ModulesAlloc.Allocate())
1189+
Module(ModuleConstructorTag{}, Name, SourceLocation(), /*Parent=*/nullptr,
1190+
IsFramework, /*IsExplicit=*/false, NumCreatedModules++);
11791191
Result->ShadowingModule = ShadowingModule;
11801192
Result->markUnavailable(/*Unimportable*/true);
11811193
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)