@@ -118,8 +118,8 @@ DependencyScanningFilesystemSharedCache::CacheShard::findEntryByFilename(
118
118
StringRef Filename) const {
119
119
assert (llvm::sys::path::is_absolute_gnu (Filename));
120
120
std::lock_guard<std::mutex> LockGuard (CacheLock);
121
- auto It = EntriesByFilename .find (Filename);
122
- return It == EntriesByFilename .end () ? nullptr : It->getValue ();
121
+ auto It = CacheByFilename .find (Filename);
122
+ return It == CacheByFilename .end () ? nullptr : It->getValue (). first ;
123
123
}
124
124
125
125
const CachedFileSystemEntry *
@@ -135,11 +135,16 @@ DependencyScanningFilesystemSharedCache::CacheShard::
135
135
getOrEmplaceEntryForFilename (StringRef Filename,
136
136
llvm::ErrorOr<llvm::vfs::Status> Stat) {
137
137
std::lock_guard<std::mutex> LockGuard (CacheLock);
138
- auto Insertion = EntriesByFilename.insert ({Filename, nullptr });
139
- if (Insertion.second )
140
- Insertion.first ->second =
138
+ auto [It, Inserted] = CacheByFilename.insert ({Filename, {nullptr , nullptr }});
139
+ auto &[CachedEntry, CachedRealPath] = It->getValue ();
140
+ if (!CachedEntry) {
141
+ // The entry is not present in the shared cache. Either the cache doesn't
142
+ // know about the file at all, or it only knows about its real path.
143
+ assert ((Inserted || CachedRealPath) && " existing file with empty pair" );
144
+ CachedEntry =
141
145
new (EntryStorage.Allocate ()) CachedFileSystemEntry (std::move (Stat));
142
- return *Insertion.first ->second ;
146
+ }
147
+ return *CachedEntry;
143
148
}
144
149
145
150
const CachedFileSystemEntry &
@@ -148,24 +153,58 @@ DependencyScanningFilesystemSharedCache::CacheShard::getOrEmplaceEntryForUID(
148
153
std::unique_ptr<llvm::MemoryBuffer> Contents,
149
154
std::optional<cas::ObjectRef> CASContents) {
150
155
std::lock_guard<std::mutex> LockGuard (CacheLock);
151
- auto Insertion = EntriesByUID.insert ({UID, nullptr });
152
- if (Insertion.second ) {
156
+ auto [It, Inserted] = EntriesByUID.insert ({UID, nullptr });
157
+ auto &CachedEntry = It->getSecond ();
158
+ if (Inserted) {
153
159
CachedFileContents *StoredContents = nullptr ;
154
160
if (Contents)
155
161
StoredContents = new (ContentsStorage.Allocate ())
156
162
CachedFileContents (std::move (Contents), std::move (CASContents));
157
- Insertion. first -> second = new (EntryStorage.Allocate ())
163
+ CachedEntry = new (EntryStorage.Allocate ())
158
164
CachedFileSystemEntry (std::move (Stat), StoredContents);
159
165
}
160
- return *Insertion. first -> second ;
166
+ return *CachedEntry ;
161
167
}
162
168
163
169
const CachedFileSystemEntry &
164
170
DependencyScanningFilesystemSharedCache::CacheShard::
165
171
getOrInsertEntryForFilename (StringRef Filename,
166
172
const CachedFileSystemEntry &Entry) {
167
173
std::lock_guard<std::mutex> LockGuard (CacheLock);
168
- return *EntriesByFilename.insert ({Filename, &Entry}).first ->getValue ();
174
+ auto [It, Inserted] = CacheByFilename.insert ({Filename, {&Entry, nullptr }});
175
+ auto &[CachedEntry, CachedRealPath] = It->getValue ();
176
+ if (!Inserted || !CachedEntry)
177
+ CachedEntry = &Entry;
178
+ return *CachedEntry;
179
+ }
180
+
181
+ const CachedRealPath *
182
+ DependencyScanningFilesystemSharedCache::CacheShard::findRealPathByFilename (
183
+ StringRef Filename) const {
184
+ assert (llvm::sys::path::is_absolute_gnu (Filename));
185
+ std::lock_guard<std::mutex> LockGuard (CacheLock);
186
+ auto It = CacheByFilename.find (Filename);
187
+ return It == CacheByFilename.end () ? nullptr : It->getValue ().second ;
188
+ }
189
+
190
+ const CachedRealPath &DependencyScanningFilesystemSharedCache::CacheShard::
191
+ getOrEmplaceRealPathForFilename (StringRef Filename,
192
+ llvm::ErrorOr<llvm::StringRef> RealPath) {
193
+ std::lock_guard<std::mutex> LockGuard (CacheLock);
194
+
195
+ const CachedRealPath *&StoredRealPath = CacheByFilename[Filename].second ;
196
+ if (!StoredRealPath) {
197
+ auto OwnedRealPath = [&]() -> CachedRealPath {
198
+ if (!RealPath)
199
+ return RealPath.getError ();
200
+ return RealPath->str ();
201
+ }();
202
+
203
+ StoredRealPath = new (RealPathStorage.Allocate ())
204
+ CachedRealPath (std::move (OwnedRealPath));
205
+ }
206
+
207
+ return *StoredRealPath;
169
208
}
170
209
171
210
static bool shouldCacheStatFailures (StringRef Filename) {
@@ -334,6 +373,54 @@ DependencyScanningWorkerFilesystem::openFileForRead(const Twine &Path) {
334
373
return DepScanFile::create (Result.get ());
335
374
}
336
375
376
+ std::error_code
377
+ DependencyScanningWorkerFilesystem::getRealPath (const Twine &Path,
378
+ SmallVectorImpl<char > &Output) {
379
+ SmallString<256 > OwnedFilename;
380
+ StringRef OriginalFilename = Path.toStringRef (OwnedFilename);
381
+
382
+ SmallString<256 > PathBuf;
383
+ auto FilenameForLookup = tryGetFilenameForLookup (OriginalFilename, PathBuf);
384
+ if (!FilenameForLookup)
385
+ return FilenameForLookup.getError ();
386
+
387
+ auto HandleCachedRealPath =
388
+ [&Output](const CachedRealPath &RealPath) -> std::error_code {
389
+ if (!RealPath)
390
+ return RealPath.getError ();
391
+ Output.assign (RealPath->begin (), RealPath->end ());
392
+ return {};
393
+ };
394
+
395
+ // If we already have the result in local cache, no work required.
396
+ if (const auto *RealPath =
397
+ LocalCache.findRealPathByFilename (*FilenameForLookup))
398
+ return HandleCachedRealPath (*RealPath);
399
+
400
+ // If we have the result in the shared cache, cache it locally.
401
+ auto &Shard = SharedCache.getShardForFilename (*FilenameForLookup);
402
+ if (const auto *ShardRealPath =
403
+ Shard.findRealPathByFilename (*FilenameForLookup)) {
404
+ const auto &RealPath = LocalCache.insertRealPathForFilename (
405
+ *FilenameForLookup, *ShardRealPath);
406
+ return HandleCachedRealPath (RealPath);
407
+ }
408
+
409
+ // If we don't know the real path, compute it...
410
+ std::error_code EC = getUnderlyingFS ().getRealPath (OriginalFilename, Output);
411
+ llvm::ErrorOr<llvm::StringRef> ComputedRealPath = EC;
412
+ if (!EC)
413
+ ComputedRealPath = StringRef{Output.data (), Output.size ()};
414
+
415
+ // ...and try to write it into the shared cache. In case some other thread won
416
+ // this race and already wrote its own result there, just adopt it. Write
417
+ // whatever is in the shared cache into the local one.
418
+ const auto &RealPath = Shard.getOrEmplaceRealPathForFilename (
419
+ *FilenameForLookup, ComputedRealPath);
420
+ return HandleCachedRealPath (
421
+ LocalCache.insertRealPathForFilename (*FilenameForLookup, RealPath));
422
+ }
423
+
337
424
std::error_code DependencyScanningWorkerFilesystem::setCurrentWorkingDirectory (
338
425
const Twine &Path) {
339
426
std::error_code EC = ProxyFileSystem::setCurrentWorkingDirectory (Path);
0 commit comments