Skip to content

Commit 370b01f

Browse files
committed
Address comments
1 parent dcdd18a commit 370b01f

File tree

1 file changed

+100
-69
lines changed

1 file changed

+100
-69
lines changed

clang-tools-extra/clangd/ModulesBuilder.cpp

Lines changed: 100 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,47 @@ class FailedPrerequisiteModules : public PrerequisiteModules {
9595
}
9696
};
9797

98+
struct ModuleFile;
99+
100+
// ReusablePrerequisiteModules - stands for PrerequisiteModules for which all
101+
// the required modules are built successfully. All the module files
102+
// are owned by the modules builder.
103+
class ReusablePrerequisiteModules : public PrerequisiteModules {
104+
public:
105+
ReusablePrerequisiteModules() = default;
106+
107+
ReusablePrerequisiteModules(const ReusablePrerequisiteModules &Other) =
108+
default;
109+
ReusablePrerequisiteModules &
110+
operator=(const ReusablePrerequisiteModules &) = default;
111+
ReusablePrerequisiteModules(ReusablePrerequisiteModules &&) = delete;
112+
ReusablePrerequisiteModules
113+
operator=(ReusablePrerequisiteModules &&) = delete;
114+
115+
~ReusablePrerequisiteModules() override = default;
116+
117+
void adjustHeaderSearchOptions(HeaderSearchOptions &Options) const override;
118+
119+
bool canReuse(const CompilerInvocation &CI,
120+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>) const override;
121+
122+
bool isModuleUnitBuilt(llvm::StringRef ModuleName) const {
123+
return BuiltModuleNames.contains(ModuleName);
124+
}
125+
126+
void addModuleFile(std::shared_ptr<const ModuleFile> ModuleFile);
127+
128+
private:
129+
llvm::SmallVector<std::shared_ptr<const ModuleFile>, 8> RequiredModules;
130+
// A helper class to speedup the query if a module is built.
131+
llvm::StringSet<> BuiltModuleNames;
132+
};
133+
98134
struct ModuleFile {
99-
ModuleFile(StringRef ModuleName, PathRef ModuleFilePath)
100-
: ModuleName(ModuleName.str()), ModuleFilePath(ModuleFilePath.str()) {}
135+
ModuleFile(StringRef ModuleName, PathRef ModuleFilePath,
136+
const ReusablePrerequisiteModules &RequiredModuleFiles)
137+
: ModuleName(ModuleName.str()), ModuleFilePath(ModuleFilePath.str()),
138+
RequiredModuleFiles(RequiredModuleFiles) {}
101139

102140
ModuleFile() = delete;
103141

@@ -133,8 +171,27 @@ struct ModuleFile {
133171
private:
134172
std::string ModuleName;
135173
std::string ModuleFilePath;
174+
175+
// The required module files. We need to share the ownership for required
176+
// module files.
177+
ReusablePrerequisiteModules RequiredModuleFiles;
136178
};
137179

180+
void ReusablePrerequisiteModules::adjustHeaderSearchOptions(
181+
HeaderSearchOptions &Options) const {
182+
// Appending all built module files.
183+
for (const auto &RequiredModule : RequiredModules)
184+
Options.PrebuiltModuleFiles.insert_or_assign(
185+
RequiredModule->getModuleName().str(),
186+
RequiredModule->getModuleFilePath().str());
187+
}
188+
189+
void ReusablePrerequisiteModules::addModuleFile(
190+
std::shared_ptr<const ModuleFile> ModuleFile) {
191+
BuiltModuleNames.insert(ModuleFile->getModuleName());
192+
RequiredModules.emplace_back(std::move(ModuleFile));
193+
}
194+
138195
bool IsModuleFileUpToDate(PathRef ModuleFilePath,
139196
const PrerequisiteModules &RequisiteModules,
140197
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
@@ -199,48 +256,6 @@ bool IsModuleFilesUpToDate(
199256
});
200257
}
201258

202-
// ReusablePrerequisiteModules - stands for PrerequisiteModules for which all
203-
// the required modules are built successfully. All the module files
204-
// are owned by the modules builder.
205-
class ReusablePrerequisiteModules : public PrerequisiteModules {
206-
public:
207-
ReusablePrerequisiteModules() = default;
208-
209-
ReusablePrerequisiteModules(const ReusablePrerequisiteModules &) = delete;
210-
ReusablePrerequisiteModules
211-
operator=(const ReusablePrerequisiteModules &) = delete;
212-
ReusablePrerequisiteModules(ReusablePrerequisiteModules &&) = delete;
213-
ReusablePrerequisiteModules
214-
operator=(ReusablePrerequisiteModules &&) = delete;
215-
216-
~ReusablePrerequisiteModules() override = default;
217-
218-
void adjustHeaderSearchOptions(HeaderSearchOptions &Options) const override {
219-
// Appending all built module files.
220-
for (auto &RequiredModule : RequiredModules)
221-
Options.PrebuiltModuleFiles.insert_or_assign(
222-
RequiredModule->getModuleName().str(),
223-
RequiredModule->getModuleFilePath().str());
224-
}
225-
226-
bool canReuse(const CompilerInvocation &CI,
227-
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>) const override;
228-
229-
bool isModuleUnitBuilt(llvm::StringRef ModuleName) const {
230-
return BuiltModuleNames.contains(ModuleName);
231-
}
232-
233-
void addModuleFile(std::shared_ptr<ModuleFile> BMI) {
234-
BuiltModuleNames.insert(BMI->getModuleName());
235-
RequiredModules.emplace_back(std::move(BMI));
236-
}
237-
238-
private:
239-
llvm::SmallVector<std::shared_ptr<ModuleFile>, 8> RequiredModules;
240-
// A helper class to speedup the query if a module is built.
241-
llvm::StringSet<> BuiltModuleNames;
242-
};
243-
244259
/// Build a module file for module with `ModuleName`. The information of built
245260
/// module file are stored in \param BuiltModuleFiles.
246261
llvm::Expected<ModuleFile>
@@ -294,7 +309,7 @@ buildModuleFile(llvm::StringRef ModuleName, PathRef ModuleUnitFileName,
294309
if (Clang->getDiagnostics().hasErrorOccurred())
295310
return llvm::createStringError("Compilation failed");
296311

297-
return ModuleFile{ModuleName, Inputs.CompileCommand.Output};
312+
return ModuleFile{ModuleName, Inputs.CompileCommand.Output, BuiltModuleFiles};
298313
}
299314

300315
bool ReusablePrerequisiteModules::canReuse(
@@ -319,30 +334,32 @@ class ModuleFileCache {
319334
ReusablePrerequisiteModules &RequiredModules);
320335
const GlobalCompilationDatabase &getCDB() const { return CDB; }
321336

322-
std::shared_ptr<ModuleFile>
337+
std::shared_ptr<const ModuleFile>
323338
getValidModuleFile(StringRef ModuleName, ProjectModules &MDB,
324339
const ThreadsafeFS &TFS,
325340
PrerequisiteModules &BuiltModuleFiles);
326341

327-
void add(StringRef ModuleName, std::shared_ptr<ModuleFile> ModuleFile) {
328-
std::lock_guard<std::mutex> _(ModuleFilesMutex);
342+
void add(StringRef ModuleName, std::shared_ptr<const ModuleFile> ModuleFile) {
343+
std::lock_guard<std::mutex> Lock(ModuleFilesMutex);
329344

330345
ModuleFiles.insert_or_assign(ModuleName, ModuleFile);
331346
}
332347

333348
private:
334349
const GlobalCompilationDatabase &CDB;
335350

336-
llvm::StringMap<std::shared_ptr<ModuleFile>> ModuleFiles;
351+
llvm::StringMap<std::weak_ptr<const ModuleFile>> ModuleFiles;
337352
// Mutex to guard accesses to ModuleFiles.
338353
std::mutex ModuleFilesMutex;
339354
};
340355

341356
/// Collect the directly and indirectly required module names for \param
342357
/// ModuleName. The \param ModuleName is guaranteed to be the first element in
343358
/// \param ModuleNames.
344-
void getAllRequiredModules(ProjectModules &MDB, StringRef ModuleName,
345-
llvm::SmallVector<StringRef> &ModuleNames) {
359+
llvm::SmallVector<StringRef> getAllRequiredModules(ProjectModules &MDB,
360+
StringRef ModuleName) {
361+
llvm::SmallVector<StringRef> ModuleNames;
362+
346363
std::queue<StringRef> Worklist;
347364
llvm::StringSet<> ModuleNamesSet;
348365
Worklist.push(ModuleName);
@@ -361,46 +378,60 @@ void getAllRequiredModules(ProjectModules &MDB, StringRef ModuleName,
361378
if (!ModuleNamesSet.contains(RequiredModuleName))
362379
Worklist.push(RequiredModuleName);
363380
}
381+
382+
return ModuleNames;
364383
}
365384

366-
std::shared_ptr<ModuleFile>
385+
std::shared_ptr<const ModuleFile>
367386
ModuleFileCache::getValidModuleFile(StringRef ModuleName, ProjectModules &MDB,
368387
const ThreadsafeFS &TFS,
369388
PrerequisiteModules &BuiltModuleFiles) {
370389
{
371-
std::lock_guard<std::mutex> _(ModuleFilesMutex);
390+
std::lock_guard<std::mutex> Lock(ModuleFilesMutex);
391+
392+
auto Iter = ModuleFiles.find(ModuleName);
393+
if (Iter == ModuleFiles.end())
394+
return nullptr;
372395

373-
if (ModuleFiles.find(ModuleName) == ModuleFiles.end())
396+
if (Iter->second.expired()) {
397+
ModuleFiles.erase(Iter);
374398
return nullptr;
399+
}
375400
}
376401

377-
llvm::SmallVector<StringRef> ModuleNames;
378-
getAllRequiredModules(MDB, ModuleName, ModuleNames);
402+
llvm::SmallVector<StringRef> ModuleNames =
403+
getAllRequiredModules(MDB, ModuleName);
379404

380-
llvm::SmallVector<std::shared_ptr<ModuleFile>> RequiredModuleFiles;
405+
llvm::SmallVector<std::shared_ptr<const ModuleFile>> RequiredModuleFiles;
381406

382407
{
383-
std::lock_guard<std::mutex> _(ModuleFilesMutex);
408+
std::lock_guard<std::mutex> Lock(ModuleFilesMutex);
384409

385410
for (StringRef ModuleName : ModuleNames) {
386411
auto Iter = ModuleFiles.find(ModuleName);
387412
if (Iter == ModuleFiles.end())
388413
return nullptr;
389414

390-
RequiredModuleFiles.push_back(Iter->second);
415+
if (Iter->second.expired()) {
416+
ModuleFiles.erase(Iter);
417+
return nullptr;
418+
}
419+
420+
RequiredModuleFiles.push_back(Iter->second.lock());
391421
}
392422
}
393423

394-
if (RequiredModuleFiles.empty())
395-
return nullptr;
424+
assert(!RequiredModuleFiles.empty());
396425

397-
if (llvm::all_of(RequiredModuleFiles, [&](auto MF) {
398-
return IsModuleFileUpToDate(MF->getModuleFilePath(), BuiltModuleFiles,
399-
TFS.view(std::nullopt));
400-
}))
401-
return RequiredModuleFiles[0];
426+
if (llvm::any_of(RequiredModuleFiles,
427+
[&](std::shared_ptr<const ModuleFile> MF) {
428+
return !IsModuleFileUpToDate(MF->getModuleFilePath(),
429+
BuiltModuleFiles,
430+
TFS.view(std::nullopt));
431+
}))
432+
return nullptr;
402433

403-
return nullptr;
434+
return RequiredModuleFiles[0];
404435
}
405436
} // namespace
406437

@@ -443,7 +474,7 @@ llvm::Error ModulesBuilder::ModulesBuilderImpl::getOrBuildModuleFile(
443474
return llvm::createStringError(
444475
llvm::formatv("Failed to build module {0}", RequiredModuleName));
445476

446-
if (std::shared_ptr<ModuleFile> Cached =
477+
if (std::shared_ptr<const ModuleFile> Cached =
447478
Cache.getValidModuleFile(ModuleName, MDB, TFS, BuiltModuleFiles)) {
448479
log("Reusing module {0} from {1}", ModuleName, Cached->getModuleFilePath());
449480
BuiltModuleFiles.addModuleFile(Cached);
@@ -462,7 +493,7 @@ llvm::Error ModulesBuilder::ModulesBuilderImpl::getOrBuildModuleFile(
462493
return Err;
463494

464495
log("Built module {0} to {1}", ModuleName, MF->getModuleFilePath());
465-
auto BuiltModuleFile = std::make_shared<ModuleFile>(std::move(*MF));
496+
auto BuiltModuleFile = std::make_shared<const ModuleFile>(std::move(*MF));
466497
Cache.add(ModuleName, BuiltModuleFile);
467498
BuiltModuleFiles.addModuleFile(std::move(BuiltModuleFile));
468499

0 commit comments

Comments
 (0)