@@ -113,8 +113,8 @@ DependencyScanningFilesystemSharedCache::CacheShard::findEntryByFilename(
113113 StringRef Filename) const {
114114 assert (llvm::sys::path::is_absolute_gnu (Filename));
115115 std::lock_guard<std::mutex> LockGuard (CacheLock);
116- auto It = EntriesByFilename .find (Filename);
117- return It == EntriesByFilename .end () ? nullptr : It->getValue ();
116+ auto It = CacheByFilename .find (Filename);
117+ return It == CacheByFilename .end () ? nullptr : It->getValue (). first ;
118118}
119119
120120const CachedFileSystemEntry *
@@ -130,36 +130,75 @@ DependencyScanningFilesystemSharedCache::CacheShard::
130130 getOrEmplaceEntryForFilename (StringRef Filename,
131131 llvm::ErrorOr<llvm::vfs::Status> Stat) {
132132 std::lock_guard<std::mutex> LockGuard (CacheLock);
133- auto Insertion = EntriesByFilename.insert ({Filename, nullptr });
134- if (Insertion.second )
135- Insertion.first ->second =
133+ auto [It, Inserted] = CacheByFilename.insert ({Filename, {nullptr , nullptr }});
134+ auto &[CachedEntry, CachedRealPath] = It->getValue ();
135+ if (!CachedEntry) {
136+ // The entry is not present in the shared cache. Either the cache doesn't
137+ // know about the file at all, or it only knows about its real path.
138+ assert ((Inserted || CachedRealPath) && " existing file with empty pair" );
139+ CachedEntry =
136140 new (EntryStorage.Allocate ()) CachedFileSystemEntry (std::move (Stat));
137- return *Insertion.first ->second ;
141+ }
142+ return *CachedEntry;
138143}
139144
140145const CachedFileSystemEntry &
141146DependencyScanningFilesystemSharedCache::CacheShard::getOrEmplaceEntryForUID (
142147 llvm::sys::fs::UniqueID UID, llvm::vfs::Status Stat,
143148 std::unique_ptr<llvm::MemoryBuffer> Contents) {
144149 std::lock_guard<std::mutex> LockGuard (CacheLock);
145- auto Insertion = EntriesByUID.insert ({UID, nullptr });
146- if (Insertion.second ) {
150+ auto [It, Inserted] = EntriesByUID.insert ({UID, nullptr });
151+ auto &CachedEntry = It->getSecond ();
152+ if (Inserted) {
147153 CachedFileContents *StoredContents = nullptr ;
148154 if (Contents)
149155 StoredContents = new (ContentsStorage.Allocate ())
150156 CachedFileContents (std::move (Contents));
151- Insertion. first -> second = new (EntryStorage.Allocate ())
157+ CachedEntry = new (EntryStorage.Allocate ())
152158 CachedFileSystemEntry (std::move (Stat), StoredContents);
153159 }
154- return *Insertion. first -> second ;
160+ return *CachedEntry ;
155161}
156162
157163const CachedFileSystemEntry &
158164DependencyScanningFilesystemSharedCache::CacheShard::
159165 getOrInsertEntryForFilename (StringRef Filename,
160166 const CachedFileSystemEntry &Entry) {
161167 std::lock_guard<std::mutex> LockGuard (CacheLock);
162- return *EntriesByFilename.insert ({Filename, &Entry}).first ->getValue ();
168+ auto [It, Inserted] = CacheByFilename.insert ({Filename, {&Entry, nullptr }});
169+ auto &[CachedEntry, CachedRealPath] = It->getValue ();
170+ if (!Inserted || !CachedEntry)
171+ CachedEntry = &Entry;
172+ return *CachedEntry;
173+ }
174+
175+ const CachedRealPath *
176+ DependencyScanningFilesystemSharedCache::CacheShard::findRealPathByFilename (
177+ StringRef Filename) const {
178+ assert (llvm::sys::path::is_absolute_gnu (Filename));
179+ std::lock_guard<std::mutex> LockGuard (CacheLock);
180+ auto It = CacheByFilename.find (Filename);
181+ return It == CacheByFilename.end () ? nullptr : It->getValue ().second ;
182+ }
183+
184+ const CachedRealPath &DependencyScanningFilesystemSharedCache::CacheShard::
185+ getOrEmplaceRealPathForFilename (StringRef Filename,
186+ llvm::ErrorOr<llvm::StringRef> RealPath) {
187+ std::lock_guard<std::mutex> LockGuard (CacheLock);
188+
189+ const CachedRealPath *&StoredRealPath = CacheByFilename[Filename].second ;
190+ if (!StoredRealPath) {
191+ auto OwnedRealPath = [&]() -> CachedRealPath {
192+ if (!RealPath)
193+ return RealPath.getError ();
194+ return RealPath->str ();
195+ }();
196+
197+ StoredRealPath = new (RealPathStorage.Allocate ())
198+ CachedRealPath (std::move (OwnedRealPath));
199+ }
200+
201+ return *StoredRealPath;
163202}
164203
165204static bool shouldCacheStatFailures (StringRef Filename) {
@@ -321,6 +360,54 @@ DependencyScanningWorkerFilesystem::openFileForRead(const Twine &Path) {
321360 return DepScanFile::create (Result.get ());
322361}
323362
363+ std::error_code
364+ DependencyScanningWorkerFilesystem::getRealPath (const Twine &Path,
365+ SmallVectorImpl<char > &Output) {
366+ SmallString<256 > OwnedFilename;
367+ StringRef OriginalFilename = Path.toStringRef (OwnedFilename);
368+
369+ SmallString<256 > PathBuf;
370+ auto FilenameForLookup = tryGetFilenameForLookup (OriginalFilename, PathBuf);
371+ if (!FilenameForLookup)
372+ return FilenameForLookup.getError ();
373+
374+ auto HandleCachedRealPath =
375+ [&Output](const CachedRealPath &RealPath) -> std::error_code {
376+ if (!RealPath)
377+ return RealPath.getError ();
378+ Output.assign (RealPath->begin (), RealPath->end ());
379+ return {};
380+ };
381+
382+ // If we already have the result in local cache, no work required.
383+ if (const auto *RealPath =
384+ LocalCache.findRealPathByFilename (*FilenameForLookup))
385+ return HandleCachedRealPath (*RealPath);
386+
387+ // If we have the result in the shared cache, cache it locally.
388+ auto &Shard = SharedCache.getShardForFilename (*FilenameForLookup);
389+ if (const auto *ShardRealPath =
390+ Shard.findRealPathByFilename (*FilenameForLookup)) {
391+ const auto &RealPath = LocalCache.insertRealPathForFilename (
392+ *FilenameForLookup, *ShardRealPath);
393+ return HandleCachedRealPath (RealPath);
394+ }
395+
396+ // If we don't know the real path, compute it...
397+ std::error_code EC = getUnderlyingFS ().getRealPath (OriginalFilename, Output);
398+ llvm::ErrorOr<llvm::StringRef> ComputedRealPath = EC;
399+ if (!EC)
400+ ComputedRealPath = StringRef{Output.data (), Output.size ()};
401+
402+ // ...and try to write it into the shared cache. In case some other thread won
403+ // this race and already wrote its own result there, just adopt it. Write
404+ // whatever is in the shared cache into the local one.
405+ const auto &RealPath = Shard.getOrEmplaceRealPathForFilename (
406+ *FilenameForLookup, ComputedRealPath);
407+ return HandleCachedRealPath (
408+ LocalCache.insertRealPathForFilename (*FilenameForLookup, RealPath));
409+ }
410+
324411std::error_code DependencyScanningWorkerFilesystem::setCurrentWorkingDirectory (
325412 const Twine &Path) {
326413 std::error_code EC = ProxyFileSystem::setCurrentWorkingDirectory (Path);
0 commit comments