@@ -26,27 +26,31 @@ namespace dependencies {
26
26
// / the dependency scanning filesystem.
27
27
// /
28
28
// / It represents one of the following:
29
- // / - an opened source file with minimized contents and a stat value.
30
- // / - an opened source file with original contents and a stat value.
31
- // / - a directory entry with its stat value.
32
- // / - an error value to represent a file system error.
29
+ // / - opened file with original contents and a stat value,
30
+ // / - opened file with original contents, minimized contents and a stat value,
31
+ // / - directory entry with its stat value,
32
+ // / - filesystem error,
33
33
// / - uninitialized entry with unknown status.
34
34
class CachedFileSystemEntry {
35
35
public:
36
36
// / Creates an uninitialized entry.
37
- CachedFileSystemEntry () : MaybeStat(llvm::vfs::Status()) {}
37
+ CachedFileSystemEntry ()
38
+ : MaybeStat(llvm::vfs::Status()), MinimizedContentsAccess(nullptr ) {}
38
39
39
40
// / Initialize the cached file system entry.
40
41
void init (llvm::ErrorOr<llvm::vfs::Status> &&MaybeStatus, StringRef Filename,
41
- llvm::vfs::FileSystem &FS, bool ShouldMinimize = true );
42
+ llvm::vfs::FileSystem &FS);
42
43
43
44
// / Initialize the entry as file with minimized or original contents.
44
45
// /
45
46
// / The filesystem opens the file even for `stat` calls open to avoid the
46
47
// / issues with stat + open of minimized files that might lead to a
47
48
// / mismatching size of the file.
48
- llvm::ErrorOr<llvm::vfs::Status>
49
- initFile (StringRef Filename, llvm::vfs::FileSystem &FS, bool Minimize = true );
49
+ llvm::ErrorOr<llvm::vfs::Status> initFile (StringRef Filename,
50
+ llvm::vfs::FileSystem &FS);
51
+
52
+ // / Minimize contents of the file.
53
+ void minimizeFile ();
50
54
51
55
// / \returns True if the entry is initialized.
52
56
bool isInitialized () const {
@@ -56,13 +60,38 @@ class CachedFileSystemEntry {
56
60
// / \returns True if the current entry points to a directory.
57
61
bool isDirectory () const { return MaybeStat && MaybeStat->isDirectory (); }
58
62
59
- // / \returns The error or the file's contents.
60
- llvm::ErrorOr<StringRef> getContents () const {
63
+ // / \returns The error or the file's original contents.
64
+ llvm::ErrorOr<StringRef> getOriginalContents () const {
65
+ if (!MaybeStat)
66
+ return MaybeStat.getError ();
67
+ assert (!MaybeStat->isDirectory () && " not a file" );
68
+ assert (isInitialized () && " not initialized" );
69
+ assert (OriginalContents && " not read" );
70
+ return OriginalContents->getBuffer ();
71
+ }
72
+
73
+ // / \returns The error or the file's minimized contents.
74
+ llvm::ErrorOr<StringRef> getMinimizedContents () const {
61
75
if (!MaybeStat)
62
76
return MaybeStat.getError ();
63
77
assert (!MaybeStat->isDirectory () && " not a file" );
64
78
assert (isInitialized () && " not initialized" );
65
- return Contents->getBuffer ();
79
+ llvm::MemoryBuffer *Buffer = MinimizedContentsAccess.load ();
80
+ assert (Buffer && " not minimized" );
81
+ return Buffer->getBuffer ();
82
+ }
83
+
84
+ // / \returns True if this entry represents a file that can be read.
85
+ bool isReadable () const { return MaybeStat && !MaybeStat->isDirectory (); }
86
+
87
+ // / \returns True if this cached entry needs to be updated.
88
+ bool needsUpdate (bool ShouldBeMinimized) const {
89
+ return isReadable () && needsMinimization (ShouldBeMinimized);
90
+ }
91
+
92
+ // / \returns True if the contents of this entry need to be minimized.
93
+ bool needsMinimization (bool ShouldBeMinimized) const {
94
+ return ShouldBeMinimized && !MinimizedContentsAccess.load ();
66
95
}
67
96
68
97
// / \returns The error or the status of the entry.
@@ -83,15 +112,16 @@ class CachedFileSystemEntry {
83
112
return PPSkippedRangeMapping;
84
113
}
85
114
86
- CachedFileSystemEntry (CachedFileSystemEntry &&) = default ;
87
- CachedFileSystemEntry &operator =(CachedFileSystemEntry &&) = default ;
88
-
89
- CachedFileSystemEntry (const CachedFileSystemEntry &) = delete ;
90
- CachedFileSystemEntry &operator =(const CachedFileSystemEntry &) = delete ;
91
-
92
115
private:
93
116
llvm::ErrorOr<llvm::vfs::Status> MaybeStat;
94
- std::unique_ptr<llvm::MemoryBuffer> Contents;
117
+ std::unique_ptr<llvm::MemoryBuffer> OriginalContents;
118
+
119
+ // / Owning storage for the minimized file contents.
120
+ std::unique_ptr<llvm::MemoryBuffer> MinimizedContentsStorage;
121
+ // / Atomic view of the minimized file contents.
122
+ // / This prevents data races when multiple threads call `needsMinimization`.
123
+ std::atomic<llvm::MemoryBuffer *> MinimizedContentsAccess;
124
+
95
125
PreprocessorSkippedRangeMapping PPSkippedRangeMapping;
96
126
};
97
127
@@ -108,61 +138,70 @@ class DependencyScanningFilesystemSharedCache {
108
138
CachedFileSystemEntry Value;
109
139
};
110
140
141
+ DependencyScanningFilesystemSharedCache ();
142
+
111
143
// / Returns a cache entry for the corresponding key.
112
144
// /
113
145
// / A new cache entry is created if the key is not in the cache. This is a
114
146
// / thread safe call.
115
- SharedFileSystemEntry &get (StringRef Key, bool Minimized );
147
+ SharedFileSystemEntry &get (StringRef Key);
116
148
117
149
private:
118
- class SingleCache {
119
- public:
120
- SingleCache ();
121
-
122
- SharedFileSystemEntry &get (StringRef Key);
123
-
124
- private:
125
- struct CacheShard {
126
- std::mutex CacheLock;
127
- llvm::StringMap<SharedFileSystemEntry, llvm::BumpPtrAllocator> Cache;
128
- };
129
- std::unique_ptr<CacheShard[]> CacheShards;
130
- unsigned NumShards;
150
+ struct CacheShard {
151
+ std::mutex CacheLock;
152
+ llvm::StringMap<SharedFileSystemEntry, llvm::BumpPtrAllocator> Cache;
131
153
};
132
-
133
- SingleCache CacheMinimized;
134
- SingleCache CacheOriginal;
154
+ std::unique_ptr<CacheShard[]> CacheShards;
155
+ unsigned NumShards;
135
156
};
136
157
137
158
// / This class is a local cache, that caches the 'stat' and 'open' calls to the
138
159
// / underlying real file system. It distinguishes between minimized and original
139
160
// / files.
140
161
class DependencyScanningFilesystemLocalCache {
141
- private:
142
- using SingleCache =
143
- llvm::StringMap<const CachedFileSystemEntry *, llvm::BumpPtrAllocator>;
162
+ llvm::StringMap<const CachedFileSystemEntry *, llvm::BumpPtrAllocator> Cache;
144
163
145
- SingleCache CacheMinimized;
146
- SingleCache CacheOriginal;
147
-
148
- SingleCache &selectCache (bool Minimized) {
149
- return Minimized ? CacheMinimized : CacheOriginal;
164
+ public:
165
+ const CachedFileSystemEntry *getCachedEntry (StringRef Filename) {
166
+ return Cache[Filename];
150
167
}
168
+ };
169
+
170
+ // / Reference to a CachedFileSystemEntry.
171
+ // / If the underlying entry is an opened file, this wrapper returns the correct
172
+ // / contents (original or minimized) and ensures consistency with file size
173
+ // / reported by status.
174
+ class EntryRef {
175
+ // / For entry that is an opened file, this bit signifies whether its contents
176
+ // / are minimized.
177
+ bool Minimized;
178
+
179
+ // / The underlying cached entry.
180
+ const CachedFileSystemEntry *Entry;
151
181
152
182
public:
153
- void setCachedEntry (StringRef Filename, bool Minimized,
154
- const CachedFileSystemEntry *Entry) {
155
- SingleCache &Cache = selectCache (Minimized);
156
- bool IsInserted = Cache.try_emplace (Filename, Entry).second ;
157
- (void )IsInserted;
158
- assert (IsInserted && " local cache is updated more than once" );
183
+ EntryRef (bool Minimized, const CachedFileSystemEntry *Entry)
184
+ : Minimized(Minimized), Entry(Entry) {}
185
+
186
+ llvm::ErrorOr<llvm::vfs::Status> getStatus () const {
187
+ auto MaybeStat = Entry->getStatus ();
188
+ if (!MaybeStat || MaybeStat->isDirectory ())
189
+ return MaybeStat;
190
+ return llvm::vfs::Status::copyWithNewSize (*MaybeStat,
191
+ getContents ()->size ());
192
+ }
193
+
194
+ bool isDirectory () const { return Entry->isDirectory (); }
195
+
196
+ StringRef getName () const { return Entry->getName (); }
197
+
198
+ llvm::ErrorOr<StringRef> getContents () const {
199
+ return Minimized ? Entry->getMinimizedContents ()
200
+ : Entry->getOriginalContents ();
159
201
}
160
202
161
- const CachedFileSystemEntry *getCachedEntry (StringRef Filename,
162
- bool Minimized) {
163
- SingleCache &Cache = selectCache (Minimized);
164
- auto It = Cache.find (Filename);
165
- return It == Cache.end () ? nullptr : It->getValue ();
203
+ const PreprocessorSkippedRangeMapping *getPPSkippedRangeMapping () const {
204
+ return Minimized ? &Entry->getPPSkippedRangeMapping () : nullptr ;
166
205
}
167
206
};
168
207
@@ -197,8 +236,7 @@ class DependencyScanningWorkerFilesystem : public llvm::vfs::ProxyFileSystem {
197
236
// / Check whether the file should be minimized.
198
237
bool shouldMinimize (StringRef Filename);
199
238
200
- llvm::ErrorOr<const CachedFileSystemEntry *>
201
- getOrCreateFileSystemEntry (const StringRef Filename);
239
+ llvm::ErrorOr<EntryRef> getOrCreateFileSystemEntry (StringRef Filename);
202
240
203
241
// / The global cache shared between worker threads.
204
242
DependencyScanningFilesystemSharedCache &SharedCache;
0 commit comments