Skip to content

Commit 572fc4e

Browse files
committed
[SourceKit] Ensure ASTCache is guarded by mutex
There were a couple of accesses not guarded by `CacheMtx`, introduce a couple of methods that guard them, renaming `getASTProducer` while here. Also make sure we don't ever insert a producer after it has been purposefully removed by e.g a close that removes the cached AST.
1 parent 74ed041 commit 572fc4e

File tree

1 file changed

+33
-5
lines changed

1 file changed

+33
-5
lines changed

tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,16 @@ struct SwiftASTManager::Implementation {
631631
});
632632
}
633633

634-
ASTProducerRef getASTProducer(SwiftInvocationRef InvokRef);
634+
/// Retrieve the ASTProducer for a given invocation, creating one if needed.
635+
ASTProducerRef getOrCreateASTProducer(SwiftInvocationRef InvokRef);
636+
637+
/// Retrieve the ASTProducer for a given invocation, returning \c nullopt if
638+
/// not present.
639+
std::optional<ASTProducerRef> getASTProducer(SwiftInvocationRef Invok);
640+
641+
/// Updates the cache entry to account for any changes to the ASTProducer
642+
/// for the given invocation.
643+
void updateASTProducer(SwiftInvocationRef Invok);
635644

636645
FileContent
637646
getFileContent(StringRef FilePath, bool IsPrimary,
@@ -780,7 +789,7 @@ void SwiftASTManager::processASTAsync(
780789
const void *OncePerASTToken, SourceKitCancellationToken CancellationToken,
781790
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fileSystem) {
782791
assert(fileSystem);
783-
ASTProducerRef Producer = Impl.getASTProducer(InvokRef);
792+
ASTProducerRef Producer = Impl.getOrCreateASTProducer(InvokRef);
784793

785794
Impl.cleanDeletedConsumers();
786795
{
@@ -816,12 +825,31 @@ void SwiftASTManager::processASTAsync(
816825
});
817826
}
818827

828+
std::optional<ASTProducerRef>
829+
SwiftASTManager::Implementation::getASTProducer(SwiftInvocationRef Invok) {
830+
llvm::sys::ScopedLock L(CacheMtx);
831+
return ASTCache.get(Invok->Impl.Key);
832+
}
833+
834+
void SwiftASTManager::Implementation::updateASTProducer(
835+
SwiftInvocationRef Invok) {
836+
llvm::sys::ScopedLock L(CacheMtx);
837+
838+
// Get and set the producer to update its cost in the cache. If we don't
839+
// have a value, then this is a race where we've removed the cached AST, but
840+
// still have a build waiting to complete after cancellation, we don't need
841+
// to do anything in that case.
842+
if (auto Producer = ASTCache.get(Invok->Impl.Key))
843+
ASTCache.set(Invok->Impl.Key, *Producer);
844+
}
845+
819846
void SwiftASTManager::removeCachedAST(SwiftInvocationRef Invok) {
847+
llvm::sys::ScopedLock L(Impl.CacheMtx);
820848
Impl.ASTCache.remove(Invok->Impl.Key);
821849
}
822850

823-
ASTProducerRef
824-
SwiftASTManager::Implementation::getASTProducer(SwiftInvocationRef InvokRef) {
851+
ASTProducerRef SwiftASTManager::Implementation::getOrCreateASTProducer(
852+
SwiftInvocationRef InvokRef) {
825853
llvm::sys::ScopedLock L(CacheMtx);
826854
std::optional<ASTProducerRef> OptProducer = ASTCache.get(InvokRef->Impl.Key);
827855
if (OptProducer.has_value())
@@ -1342,7 +1370,7 @@ void ASTProducer::enqueueConsumer(
13421370
[This]() { This->cleanBuildOperations(); });
13431371
// Re-register the object with the cache to update its memory
13441372
// cost.
1345-
Mgr->Impl.ASTCache.set(This->InvokRef->Impl.Key, This);
1373+
Mgr->Impl.updateASTProducer(This->InvokRef);
13461374
}
13471375
};
13481376

0 commit comments

Comments
 (0)