@@ -230,7 +230,7 @@ namespace {
230
230
231
231
typedef uint64_t BufferStamp;
232
232
233
- struct FileContent {
233
+ struct FileContent : llvm::RefCountedBase<FileContent> {
234
234
ImmutableTextSnapshotRef Snapshot;
235
235
std::string Filename;
236
236
std::unique_ptr<llvm::MemoryBuffer> Buffer;
@@ -248,6 +248,8 @@ struct FileContent {
248
248
}
249
249
};
250
250
251
+ using FileContentRef = llvm::IntrusiveRefCntPtr<FileContent>;
252
+
251
253
// / An \c ASTBuildOperations builds an AST. Once the AST is built, it informs
252
254
// / a list of \c SwiftASTConsumers about the built AST.
253
255
// / It also supports cancellation with the following paradigm: If an \c
@@ -299,7 +301,9 @@ class ASTBuildOperation
299
301
// / Parameters necessary to build the AST.
300
302
const SwiftInvocationRef InvokRef;
301
303
const IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem;
302
- const std::vector<ImmutableTextSnapshotRef> Snapshots;
304
+
305
+ // / The contents of all explicit input files of the compiler invoation.
306
+ const std::vector<FileContentRef> FileContents;
303
307
304
308
// / Stamps of files used to build the AST. \c Stamps contains the stamps of
305
309
// / all explicit input files, which can be determined at construction time of
@@ -357,38 +361,33 @@ class ASTBuildOperation
357
361
// / depends on the severity of the error.
358
362
ASTUnitRef buildASTUnit (std::string &Error);
359
363
360
- // / Retrieve the contents of all files needed for the compiler invocation to
361
- // / build this AST. For files contained in \c Snapshots use the snapshot's
362
- // / content. For all other files, consult the file system.
363
- void findSnapshotAndOpenFiles (SmallVectorImpl<FileContent> &Contents,
364
- std::string &Error) const ;
365
-
366
364
// / Transition the build operation to \p NewState, asserting that the current
367
365
// / state is \p ExpectedOldState.
368
366
void transitionToState (State NewState, State ExpectedOldState) {
369
367
assert (OperationState == ExpectedOldState);
370
368
OperationState = NewState;
371
369
}
372
370
373
- // / Create a vector of text snapshots containing all files explicitly
371
+ // / Create a vector of \c FileContents containing all files explicitly
374
372
// / referenced by the compiler invocation and a vector of buffer stamps of
375
373
// / those files.
376
- std::pair<std::vector<ImmutableTextSnapshotRef >, std::vector<BufferStamp>>
377
- snapshotAndStampsForFilesInCompilerInvocation ();
374
+ std::pair<std::vector<FileContentRef >, std::vector<BufferStamp>>
375
+ fileContentsAndStampsForFilesInCompilerInvocation ();
378
376
379
377
public:
380
378
ASTBuildOperation (IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
381
379
SwiftInvocationRef InvokRef, SwiftASTManagerRef ASTManager,
382
380
std::function<void (void )> DidFinishCallback)
383
381
: InvokRef(InvokRef), FileSystem(FileSystem), ASTManager(ASTManager),
384
382
DidFinishCallback (DidFinishCallback) {
385
- auto SnapshotsAndStamps = snapshotAndStampsForFilesInCompilerInvocation ();
383
+ auto FileContentsAndStamps =
384
+ fileContentsAndStampsForFilesInCompilerInvocation ();
386
385
// const_cast is fine here. We just want to guard against modifying these
387
386
// fields later on. It's fine to set them in the constructor.
388
- const_cast <std::vector<ImmutableTextSnapshotRef > &>(this ->Snapshots ) =
389
- SnapshotsAndStamps .first ;
387
+ const_cast <std::vector<FileContentRef > &>(this ->FileContents ) =
388
+ std::move (FileContentsAndStamps .first ) ;
390
389
const_cast <std::vector<BufferStamp> &>(this ->Stamps ) =
391
- SnapshotsAndStamps .second ;
390
+ FileContentsAndStamps .second ;
392
391
}
393
392
394
393
~ASTBuildOperation () {
@@ -398,7 +397,7 @@ class ASTBuildOperation
398
397
" not receive their callback." );
399
398
}
400
399
401
- ArrayRef<ImmutableTextSnapshotRef> getSnapshots () const { return Snapshots ; }
400
+ ArrayRef<FileContentRef> getFileContents () const { return FileContents ; }
402
401
403
402
// / Returns true if the build operation has finished.
404
403
bool isFinished () {
@@ -413,7 +412,7 @@ class ASTBuildOperation
413
412
}
414
413
415
414
size_t getMemoryCost () {
416
- return sizeof (*this ) + getVectorMemoryCost (Snapshots ) +
415
+ return sizeof (*this ) + getVectorMemoryCost (FileContents ) +
417
416
getVectorMemoryCost (Stamps) + Result.getMemoryCost ();
418
417
}
419
418
@@ -609,7 +608,7 @@ struct SwiftASTManager::Implementation {
609
608
610
609
ASTProducerRef getASTProducer (SwiftInvocationRef InvokRef);
611
610
612
- FileContent
611
+ FileContentRef
613
612
getFileContent (StringRef FilePath, bool IsPrimary,
614
613
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
615
614
std::string &Error) const ;
@@ -644,10 +643,10 @@ SwiftASTManager::getMemoryBuffer(StringRef Filename, std::string &Error) {
644
643
}
645
644
646
645
static FrontendInputsAndOutputs
647
- convertFileContentsToInputs (const SmallVectorImpl<FileContent> & contents) {
646
+ convertFileContentsToInputs (ArrayRef<FileContentRef> contents) {
648
647
FrontendInputsAndOutputs inputsAndOutputs;
649
- for (const FileContent & content : contents)
650
- inputsAndOutputs.addInput (InputFile (content));
648
+ for (FileContentRef content : contents)
649
+ inputsAndOutputs.addInput (InputFile (* content));
651
650
return inputsAndOutputs;
652
651
}
653
652
@@ -790,15 +789,16 @@ SwiftASTManager::Implementation::getASTProducer(SwiftInvocationRef InvokRef) {
790
789
return Producer;
791
790
}
792
791
793
- static FileContent getFileContentFromSnap (ImmutableTextSnapshotRef Snap,
794
- bool IsPrimary, StringRef FilePath) {
792
+ static FileContentRef getFileContentFromSnap (ImmutableTextSnapshotRef Snap,
793
+ bool IsPrimary,
794
+ StringRef FilePath) {
795
795
auto Buf = llvm::MemoryBuffer::getMemBufferCopy (
796
796
Snap->getBuffer ()->getText (), FilePath);
797
- return FileContent (Snap, FilePath.str (), std::move (Buf), IsPrimary,
798
- Snap->getStamp ());
797
+ return new FileContent (Snap, FilePath.str (), std::move (Buf), IsPrimary,
798
+ Snap->getStamp ());
799
799
}
800
800
801
- FileContent SwiftASTManager::Implementation::getFileContent (
801
+ FileContentRef SwiftASTManager::Implementation::getFileContent (
802
802
StringRef UnresolvedPath, bool IsPrimary,
803
803
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
804
804
std::string &Error) const {
@@ -810,8 +810,8 @@ FileContent SwiftASTManager::Implementation::getFileContent(
810
810
// FIXME: Is there a way to get timestamp and buffer for a file atomically ?
811
811
auto Stamp = getBufferStamp (FilePath, FileSystem);
812
812
auto Buffer = getMemoryBuffer (FilePath, FileSystem, Error);
813
- return FileContent (nullptr , UnresolvedPath.str (), std::move (Buffer),
814
- IsPrimary, Stamp);
813
+ return new FileContent (nullptr , UnresolvedPath.str (), std::move (Buffer),
814
+ IsPrimary, Stamp);
815
815
}
816
816
817
817
BufferStamp SwiftASTManager::Implementation::getBufferStamp (
@@ -849,13 +849,15 @@ SwiftASTManager::Implementation::getMemoryBuffer(
849
849
return nullptr ;
850
850
}
851
851
852
- std::pair<std::vector<ImmutableTextSnapshotRef >, std::vector<BufferStamp>>
853
- ASTBuildOperation::snapshotAndStampsForFilesInCompilerInvocation () {
852
+ std::pair<std::vector<FileContentRef >, std::vector<BufferStamp>>
853
+ ASTBuildOperation::fileContentsAndStampsForFilesInCompilerInvocation () {
854
854
const InvocationOptions &Opts = InvokRef->Impl .Opts ;
855
855
std::string Error; // is ignored
856
856
857
- std::vector<ImmutableTextSnapshotRef> Snapshots ;
857
+ std::vector<FileContentRef> FileContents ;
858
858
std::vector<BufferStamp> Stamps;
859
+ FileContents.reserve (
860
+ Opts.Invok .getFrontendOptions ().InputsAndOutputs .inputCount ());
859
861
Stamps.reserve (Opts.Invok .getFrontendOptions ().InputsAndOutputs .inputCount ());
860
862
861
863
// IMPORTANT: The computation of stamps must match the one in
@@ -866,33 +868,40 @@ ASTBuildOperation::snapshotAndStampsForFilesInCompilerInvocation() {
866
868
bool IsPrimary = input.isPrimary ();
867
869
auto Content =
868
870
ASTManager->Impl .getFileContent (Filename, IsPrimary, FileSystem, Error);
869
- Stamps.push_back (Content.Stamp );
870
- if (Content.Snapshot ) {
871
- Snapshots.push_back (Content.Snapshot );
871
+ if (!Content->Buffer ) {
872
+ LOG_WARN_FUNC (" failed getting file contents for " << Filename << " : "
873
+ << Error);
874
+ // File may not exist, continue and recover as if it was empty.
875
+ Content->Buffer =
876
+ llvm::WritableMemoryBuffer::getNewMemBuffer (0 , Filename);
872
877
}
878
+ Stamps.push_back (Content->Stamp );
879
+ FileContents.push_back (Content);
873
880
}
874
881
assert (Stamps.size () ==
875
882
Opts.Invok .getFrontendOptions ().InputsAndOutputs .inputCount ());
876
- return std::make_pair (Snapshots, Stamps);
883
+ assert (FileContents.size () ==
884
+ Opts.Invok .getFrontendOptions ().InputsAndOutputs .inputCount ());
885
+ return std::make_pair (FileContents, Stamps);
877
886
}
878
887
879
888
bool ASTBuildOperation::matchesSourceState (
880
889
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> OtherFileSystem) {
881
- const SwiftInvocation::Implementation &Invok = InvokRef->Impl ;
890
+ const InvocationOptions &Opts = InvokRef->Impl . Opts ;
882
891
883
892
// Check if the inputs changed.
884
893
std::vector<BufferStamp> InputStamps;
885
894
InputStamps.reserve (
886
- Invok. Opts .Invok .getFrontendOptions ().InputsAndOutputs .inputCount ());
895
+ Opts.Invok .getFrontendOptions ().InputsAndOutputs .inputCount ());
887
896
// IMPORTANT: The computation of stamps must match the one in
888
897
// snapshotAndStampsForFilesInCompilerInvocation.
889
898
for (const auto &input :
890
- Invok. Opts .Invok .getFrontendOptions ().InputsAndOutputs .getAllInputs ()) {
899
+ Opts.Invok .getFrontendOptions ().InputsAndOutputs .getAllInputs ()) {
891
900
InputStamps.push_back (
892
901
ASTManager->Impl .getBufferStamp (input.getFileName (), OtherFileSystem));
893
902
}
894
903
assert (InputStamps.size () ==
895
- Invok. Opts .Invok .getFrontendOptions ().InputsAndOutputs .inputCount ());
904
+ Opts.Invok .getFrontendOptions ().InputsAndOutputs .inputCount ());
896
905
if (Stamps != InputStamps)
897
906
return false ;
898
907
@@ -1016,13 +1025,10 @@ ASTUnitRef ASTBuildOperation::buildASTUnit(std::string &Error) {
1016
1025
Log->getOS () << Opts.Invok .getModuleName () << ' /' << Opts.PrimaryFile ;
1017
1026
}
1018
1027
1019
- SmallVector<FileContent, 8 > Contents;
1020
- findSnapshotAndOpenFiles (Contents, Error);
1021
-
1022
1028
ASTUnitRef ASTRef = new ASTUnit (++ASTUnitGeneration, ASTManager->Impl .Stats );
1023
- for (auto &Content : Contents ) {
1024
- if (Content. Snapshot )
1025
- ASTRef->Impl .Snapshots .push_back (Content. Snapshot );
1029
+ for (auto &Content : getFileContents () ) {
1030
+ if (Content-> Snapshot )
1031
+ ASTRef->Impl .Snapshots .push_back (Content-> Snapshot );
1026
1032
}
1027
1033
auto &CompIns = ASTRef->Impl .CompInst ;
1028
1034
auto &Consumer = ASTRef->Impl .CollectDiagConsumer ;
@@ -1041,7 +1047,7 @@ ASTUnitRef ASTBuildOperation::buildASTUnit(std::string &Error) {
1041
1047
1042
1048
CompilerInvocation Invocation;
1043
1049
InvokRef->Impl .Opts .applyToSubstitutingInputs (
1044
- Invocation, convertFileContentsToInputs (Contents ));
1050
+ Invocation, convertFileContentsToInputs (getFileContents () ));
1045
1051
1046
1052
Invocation.getLangOptions ().CollectParsedToken = true ;
1047
1053
@@ -1111,38 +1117,6 @@ ASTUnitRef ASTBuildOperation::buildASTUnit(std::string &Error) {
1111
1117
return ASTRef;
1112
1118
}
1113
1119
1114
- void ASTBuildOperation::findSnapshotAndOpenFiles (
1115
- SmallVectorImpl<FileContent> &Contents, std::string &Error) const {
1116
- const InvocationOptions &Opts = InvokRef->Impl .Opts ;
1117
- for (const auto &input :
1118
- Opts.Invok .getFrontendOptions ().InputsAndOutputs .getAllInputs ()) {
1119
- const std::string &File = input.getFileName ();
1120
- bool IsPrimary = input.isPrimary ();
1121
- bool FoundSnapshot = false ;
1122
- for (auto &Snap : Snapshots) {
1123
- if (Snap->getFilename () == File) {
1124
- FoundSnapshot = true ;
1125
- Contents.push_back (getFileContentFromSnap (Snap, IsPrimary, File));
1126
- break ;
1127
- }
1128
- }
1129
- if (FoundSnapshot)
1130
- continue ;
1131
-
1132
- auto Content =
1133
- ASTManager->Impl .getFileContent (File, IsPrimary, FileSystem, Error);
1134
- if (!Content.Buffer ) {
1135
- LOG_WARN_FUNC (" failed getting file contents for " << File << " : "
1136
- << Error);
1137
- // File may not exist, continue and recover as if it was empty.
1138
- Content.Buffer = llvm::WritableMemoryBuffer::getNewMemBuffer (0 , File);
1139
- }
1140
- Contents.push_back (std::move (Content));
1141
- }
1142
- assert (Contents.size () ==
1143
- Opts.Invok .getFrontendOptions ().InputsAndOutputs .inputCount ());
1144
- }
1145
-
1146
1120
void ASTBuildOperation::schedule (WorkQueue Queue) {
1147
1121
transitionToState (State::Queued, /* ExpectedOldState=*/ State::Created);
1148
1122
auto SharedThis = shared_from_this ();
@@ -1219,10 +1193,15 @@ ASTBuildOperationRef ASTProducer::getBuildOperationForConsumer(
1219
1193
if (BuildOp->isCancelled ()) {
1220
1194
continue ;
1221
1195
}
1196
+ std::vector<ImmutableTextSnapshotRef> Snapshots;
1197
+ Snapshots.reserve (BuildOp->getFileContents ().size ());
1198
+ for (auto &FileContent : BuildOp->getFileContents ()) {
1199
+ Snapshots.push_back (FileContent->Snapshot );
1200
+ }
1222
1201
if (BuildOp->matchesSourceState (FileSystem)) {
1223
1202
++Mgr->Impl .Stats ->numASTCacheHits ;
1224
1203
return BuildOp;
1225
- } else if (Consumer->canUseASTWithSnapshots (BuildOp-> getSnapshots () )) {
1204
+ } else if (Consumer->canUseASTWithSnapshots (Snapshots )) {
1226
1205
++Mgr->Impl .Stats ->numASTsUsedWithSnaphots ;
1227
1206
return BuildOp;
1228
1207
}
0 commit comments