@@ -360,16 +360,17 @@ void ModuleFileCache::remove(StringRef ModuleName) {
360
360
// / Collect the directly and indirectly required module names for \param
361
361
// / ModuleName in topological order. The \param ModuleName is guaranteed to
362
362
// / be the last element in \param ModuleNames.
363
- llvm::SmallVector<StringRef> getAllRequiredModules (ProjectModules &MDB,
363
+ llvm::SmallVector<StringRef> getAllRequiredModules (PathRef RequiredSource,
364
+ ProjectModules &MDB,
364
365
StringRef ModuleName) {
365
366
llvm::SmallVector<llvm::StringRef> ModuleNames;
366
367
llvm::StringSet<> ModuleNamesSet;
367
368
368
369
auto VisitDeps = [&](StringRef ModuleName, auto Visitor) -> void {
369
370
ModuleNamesSet.insert (ModuleName);
370
371
371
- for (StringRef RequiredModuleName :
372
- MDB.getRequiredModules (MDB. getSourceForModuleName (ModuleName)))
372
+ for (StringRef RequiredModuleName : MDB. getRequiredModules (
373
+ MDB.getSourceForModuleName (ModuleName, RequiredSource )))
373
374
if (ModuleNamesSet.insert (RequiredModuleName).second )
374
375
Visitor (RequiredModuleName, Visitor);
375
376
@@ -380,30 +381,114 @@ llvm::SmallVector<StringRef> getAllRequiredModules(ProjectModules &MDB,
380
381
return ModuleNames;
381
382
}
382
383
384
+ class CachingProjectModules : public ProjectModules {
385
+ public:
386
+ CachingProjectModules (const GlobalCompilationDatabase &CDB) : CDB(CDB) {}
387
+
388
+ std::vector<std::string> getRequiredModules (PathRef File) override {
389
+ std::unique_ptr<ProjectModules> MDB = CDB.getProjectModules (File);
390
+ if (!MDB) {
391
+ elog (" Failed to get Project Modules information for {0}" , File);
392
+ return {};
393
+ }
394
+ return MDB->getRequiredModules (File);
395
+ }
396
+
397
+ std::string getModuleNameForSource (PathRef File) override {
398
+ std::unique_ptr<ProjectModules> MDB = CDB.getProjectModules (File);
399
+ if (!MDB) {
400
+ elog (" Failed to get Project Modules information for {0}" , File);
401
+ return {};
402
+ }
403
+ return MDB->getModuleNameForSource (File);
404
+ }
405
+
406
+ void setCommandMangler (CommandMangler M) override {
407
+ // GlobalCompilationDatabase::getProjectModules() will set mangler
408
+ // for the underlying ProjectModules.
409
+ }
410
+
411
+ std::string getSourceForModuleName (llvm::StringRef ModuleName,
412
+ PathRef RequiredSrcFile) override {
413
+ std::string CachedResult;
414
+ {
415
+ std::lock_guard<std::mutex> Lock (CacheMutex);
416
+ auto Iter = ModuleNameToSourceCache.find (ModuleName);
417
+ if (Iter != ModuleNameToSourceCache.end ())
418
+ CachedResult = Iter->second ;
419
+ }
420
+
421
+ std::unique_ptr<ProjectModules> MDB =
422
+ CDB.getProjectModules (RequiredSrcFile);
423
+ if (!MDB) {
424
+ elog (" Failed to get Project Modules information for {0}" ,
425
+ RequiredSrcFile);
426
+ return {};
427
+ }
428
+
429
+ // Verify Cached Result by seeing if the source declaring the same module
430
+ // as we query.
431
+ if (!CachedResult.empty ()) {
432
+ std::string ModuleNameOfCachedSource =
433
+ MDB->getModuleNameForSource (CachedResult);
434
+ if (ModuleNameOfCachedSource == ModuleName)
435
+ return CachedResult;
436
+ else {
437
+ // Cached Result is invalid. Clear it.
438
+
439
+ std::lock_guard<std::mutex> Lock (CacheMutex);
440
+ ModuleNameToSourceCache.erase (ModuleName);
441
+ }
442
+ }
443
+
444
+ auto Result = MDB->getSourceForModuleName (ModuleName, RequiredSrcFile);
445
+
446
+ {
447
+ std::lock_guard<std::mutex> Lock (CacheMutex);
448
+ ModuleNameToSourceCache.insert ({ModuleName, Result});
449
+ }
450
+
451
+ return Result;
452
+ }
453
+
454
+ private:
455
+ const GlobalCompilationDatabase &CDB;
456
+
457
+ std::mutex CacheMutex;
458
+ llvm::StringMap<std::string> ModuleNameToSourceCache;
459
+ };
460
+
383
461
} // namespace
384
462
385
463
class ModulesBuilder ::ModulesBuilderImpl {
386
464
public:
387
- ModulesBuilderImpl (const GlobalCompilationDatabase &CDB) : Cache(CDB) {}
465
+ ModulesBuilderImpl (const GlobalCompilationDatabase &CDB)
466
+ : CachedProjectModules(CDB), Cache(CDB) {}
467
+
468
+ CachingProjectModules &getCachedProjectModules () {
469
+ return CachedProjectModules;
470
+ }
388
471
389
472
const GlobalCompilationDatabase &getCDB () const { return Cache.getCDB (); }
390
473
391
474
llvm::Error
392
- getOrBuildModuleFile (StringRef ModuleName, const ThreadsafeFS &TFS ,
393
- ProjectModules &MDB,
475
+ getOrBuildModuleFile (PathRef RequiredSource, StringRef ModuleName ,
476
+ const ThreadsafeFS &TFS, ProjectModules &MDB,
394
477
ReusablePrerequisiteModules &BuiltModuleFiles);
395
478
396
479
private:
480
+ CachingProjectModules CachedProjectModules;
397
481
ModuleFileCache Cache;
398
482
};
399
483
400
484
llvm::Error ModulesBuilder::ModulesBuilderImpl::getOrBuildModuleFile (
401
- StringRef ModuleName, const ThreadsafeFS &TFS, ProjectModules &MDB ,
402
- ReusablePrerequisiteModules &BuiltModuleFiles) {
485
+ PathRef RequiredSource, StringRef ModuleName, const ThreadsafeFS &TFS,
486
+ ProjectModules &MDB, ReusablePrerequisiteModules &BuiltModuleFiles) {
403
487
if (BuiltModuleFiles.isModuleUnitBuilt (ModuleName))
404
488
return llvm::Error::success ();
405
489
406
- PathRef ModuleUnitFileName = MDB.getSourceForModuleName (ModuleName);
490
+ std::string ModuleUnitFileName =
491
+ MDB.getSourceForModuleName (ModuleName, RequiredSource);
407
492
// / It is possible that we're meeting third party modules (modules whose
408
493
// / source are not in the project. e.g, the std module may be a third-party
409
494
// / module for most project) or something wrong with the implementation of
@@ -416,7 +501,7 @@ llvm::Error ModulesBuilder::ModulesBuilderImpl::getOrBuildModuleFile(
416
501
llvm::formatv (" Don't get the module unit for module {0}" , ModuleName));
417
502
418
503
// Get Required modules in topological order.
419
- auto ReqModuleNames = getAllRequiredModules (MDB, ModuleName);
504
+ auto ReqModuleNames = getAllRequiredModules (RequiredSource, MDB, ModuleName);
420
505
for (llvm::StringRef ReqModuleName : ReqModuleNames) {
421
506
if (BuiltModuleFiles.isModuleUnitBuilt (ModuleName))
422
507
continue ;
@@ -449,21 +534,17 @@ llvm::Error ModulesBuilder::ModulesBuilderImpl::getOrBuildModuleFile(
449
534
std::unique_ptr<PrerequisiteModules>
450
535
ModulesBuilder::buildPrerequisiteModulesFor (PathRef File,
451
536
const ThreadsafeFS &TFS) {
452
- std::unique_ptr<ProjectModules> MDB = Impl->getCDB ().getProjectModules (File);
453
- if (!MDB) {
454
- elog (" Failed to get Project Modules information for {0}" , File);
455
- return std::make_unique<FailedPrerequisiteModules>();
456
- }
537
+ ProjectModules &MDB = Impl->getCachedProjectModules ();
457
538
458
- std::vector<std::string> RequiredModuleNames = MDB-> getRequiredModules (File);
539
+ std::vector<std::string> RequiredModuleNames = MDB. getRequiredModules (File);
459
540
if (RequiredModuleNames.empty ())
460
541
return std::make_unique<ReusablePrerequisiteModules>();
461
542
462
543
auto RequiredModules = std::make_unique<ReusablePrerequisiteModules>();
463
544
for (llvm::StringRef RequiredModuleName : RequiredModuleNames) {
464
545
// Return early if there is any error.
465
546
if (llvm::Error Err = Impl->getOrBuildModuleFile (
466
- RequiredModuleName, TFS, * MDB. get () , *RequiredModules.get ())) {
547
+ File, RequiredModuleName, TFS, MDB, *RequiredModules.get ())) {
467
548
elog (" Failed to build module {0}; due to {1}" , RequiredModuleName,
468
549
toString (std::move (Err)));
469
550
return std::make_unique<FailedPrerequisiteModules>();
0 commit comments