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