@@ -357,19 +357,89 @@ void ModuleFileCache::remove(StringRef ModuleName) {
357357 ModuleFiles.erase (ModuleName);
358358}
359359
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+
360429// / Collect the directly and indirectly required module names for \param
361430// / ModuleName in topological order. The \param ModuleName is guaranteed to
362431// / be the last element in \param ModuleNames.
363- llvm::SmallVector<StringRef> getAllRequiredModules (ProjectModules &MDB,
432+ llvm::SmallVector<StringRef> getAllRequiredModules (PathRef RequiredSource,
433+ CachingProjectModules &MDB,
364434 StringRef ModuleName) {
365435 llvm::SmallVector<llvm::StringRef> ModuleNames;
366436 llvm::StringSet<> ModuleNamesSet;
367437
368438 auto VisitDeps = [&](StringRef ModuleName, auto Visitor) -> void {
369439 ModuleNamesSet.insert (ModuleName);
370440
371- for (StringRef RequiredModuleName :
372- MDB.getRequiredModules (MDB. getSourceForModuleName (ModuleName)))
441+ for (StringRef RequiredModuleName : MDB. getRequiredModules (
442+ MDB.getSourceForModuleName (ModuleName, RequiredSource )))
373443 if (ModuleNamesSet.insert (RequiredModuleName).second )
374444 Visitor (RequiredModuleName, Visitor);
375445
@@ -386,24 +456,29 @@ class ModulesBuilder::ModulesBuilderImpl {
386456public:
387457 ModulesBuilderImpl (const GlobalCompilationDatabase &CDB) : Cache(CDB) {}
388458
459+ ModuleNameToSourceCache &getProjectModulesCache () {
460+ return ProjectModulesCache;
461+ }
389462 const GlobalCompilationDatabase &getCDB () const { return Cache.getCDB (); }
390463
391464 llvm::Error
392- getOrBuildModuleFile (StringRef ModuleName, const ThreadsafeFS &TFS ,
393- ProjectModules &MDB,
465+ getOrBuildModuleFile (PathRef RequiredSource, StringRef ModuleName ,
466+ const ThreadsafeFS &TFS, CachingProjectModules &MDB,
394467 ReusablePrerequisiteModules &BuiltModuleFiles);
395468
396469private:
397470 ModuleFileCache Cache;
471+ ModuleNameToSourceCache ProjectModulesCache;
398472};
399473
400474llvm::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) {
403477 if (BuiltModuleFiles.isModuleUnitBuilt (ModuleName))
404478 return llvm::Error::success ();
405479
406- PathRef ModuleUnitFileName = MDB.getSourceForModuleName (ModuleName);
480+ std::string ModuleUnitFileName =
481+ MDB.getSourceForModuleName (ModuleName, RequiredSource);
407482 // / It is possible that we're meeting third party modules (modules whose
408483 // / source are not in the project. e.g, the std module may be a third-party
409484 // / module for most project) or something wrong with the implementation of
@@ -416,7 +491,7 @@ llvm::Error ModulesBuilder::ModulesBuilderImpl::getOrBuildModuleFile(
416491 llvm::formatv (" Don't get the module unit for module {0}" , ModuleName));
417492
418493 // Get Required modules in topological order.
419- auto ReqModuleNames = getAllRequiredModules (MDB, ModuleName);
494+ auto ReqModuleNames = getAllRequiredModules (RequiredSource, MDB, ModuleName);
420495 for (llvm::StringRef ReqModuleName : ReqModuleNames) {
421496 if (BuiltModuleFiles.isModuleUnitBuilt (ModuleName))
422497 continue ;
@@ -454,16 +529,19 @@ ModulesBuilder::buildPrerequisiteModulesFor(PathRef File,
454529 elog (" Failed to get Project Modules information for {0}" , File);
455530 return std::make_unique<FailedPrerequisiteModules>();
456531 }
532+ CachingProjectModules CachedMDB (std::move (MDB),
533+ Impl->getProjectModulesCache ());
457534
458- std::vector<std::string> RequiredModuleNames = MDB->getRequiredModules (File);
535+ std::vector<std::string> RequiredModuleNames =
536+ CachedMDB.getRequiredModules (File);
459537 if (RequiredModuleNames.empty ())
460538 return std::make_unique<ReusablePrerequisiteModules>();
461539
462540 auto RequiredModules = std::make_unique<ReusablePrerequisiteModules>();
463541 for (llvm::StringRef RequiredModuleName : RequiredModuleNames) {
464542 // Return early if there is any error.
465543 if (llvm::Error Err = Impl->getOrBuildModuleFile (
466- RequiredModuleName, TFS, *MDB. get () , *RequiredModules.get ())) {
544+ File, RequiredModuleName, TFS, CachedMDB , *RequiredModules.get ())) {
467545 elog (" Failed to build module {0}; due to {1}" , RequiredModuleName,
468546 toString (std::move (Err)));
469547 return std::make_unique<FailedPrerequisiteModules>();
0 commit comments