@@ -113,8 +113,8 @@ DependencyScanningFilesystemSharedCache::CacheShard::findEntryByFilename(
113
113
StringRef Filename) const {
114
114
assert (llvm::sys::path::is_absolute_gnu (Filename));
115
115
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 ;
118
118
}
119
119
120
120
const CachedFileSystemEntry *
@@ -130,36 +130,75 @@ DependencyScanningFilesystemSharedCache::CacheShard::
130
130
getOrEmplaceEntryForFilename (StringRef Filename,
131
131
llvm::ErrorOr<llvm::vfs::Status> Stat) {
132
132
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 =
136
140
new (EntryStorage.Allocate ()) CachedFileSystemEntry (std::move (Stat));
137
- return *Insertion.first ->second ;
141
+ }
142
+ return *CachedEntry;
138
143
}
139
144
140
145
const CachedFileSystemEntry &
141
146
DependencyScanningFilesystemSharedCache::CacheShard::getOrEmplaceEntryForUID (
142
147
llvm::sys::fs::UniqueID UID, llvm::vfs::Status Stat,
143
148
std::unique_ptr<llvm::MemoryBuffer> Contents) {
144
149
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) {
147
153
CachedFileContents *StoredContents = nullptr ;
148
154
if (Contents)
149
155
StoredContents = new (ContentsStorage.Allocate ())
150
156
CachedFileContents (std::move (Contents));
151
- Insertion. first -> second = new (EntryStorage.Allocate ())
157
+ CachedEntry = new (EntryStorage.Allocate ())
152
158
CachedFileSystemEntry (std::move (Stat), StoredContents);
153
159
}
154
- return *Insertion. first -> second ;
160
+ return *CachedEntry ;
155
161
}
156
162
157
163
const CachedFileSystemEntry &
158
164
DependencyScanningFilesystemSharedCache::CacheShard::
159
165
getOrInsertEntryForFilename (StringRef Filename,
160
166
const CachedFileSystemEntry &Entry) {
161
167
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;
163
202
}
164
203
165
204
static bool shouldCacheStatFailures (StringRef Filename) {
@@ -321,6 +360,54 @@ DependencyScanningWorkerFilesystem::openFileForRead(const Twine &Path) {
321
360
return DepScanFile::create (Result.get ());
322
361
}
323
362
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
+
324
411
std::error_code DependencyScanningWorkerFilesystem::setCurrentWorkingDirectory (
325
412
const Twine &Path) {
326
413
std::error_code EC = ProxyFileSystem::setCurrentWorkingDirectory (Path);
0 commit comments