-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[SourceKit] Support cancellation of requests while an AST is being built #38782
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
9fa75c3
to
c599eaf
Compare
@swift-ci Please build toolchain macOS |
macOS Toolchain Install command |
@swift-ci Please smoke test |
include/swift/Basic/LangOptions.h
Outdated
/// typechecking should be aborted at the next possible opportunity. | ||
/// This is used by SourceKit to cancel requests for which the result is no | ||
/// longer of interest. | ||
std::shared_ptr<bool> CancellationFlag = nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about race conditions here a bit and think it should be fine with a plain pointer. We should only have one location setting the cancellation flag to true
and that’s independent of what it’s previous content was, so there shouldn’t be any write races. And if setting the flag to true
doesn’t immediately propagate to the thread that is building the AST, it’s also fine since nobody expects the cancellation to be immediate – it’s totally fine for the type checker to e.g. continue type checking for a few more cycles. But I might be missing something.
But we could of course make it a std::atomic
. Not quite sure if that will add some performance overhead though…
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We cannot ignore the read-write race:
- The compiler is free optimize this code based on the assumption no other thread modifies the value, since it's not valid to do so.
- TSan will raise an error on this race.
But we could of course make it a std::atomic. Not quite sure if that will add some performance overhead though…
Using relaxed memory order atomic operations shouldn't cost much. On x86_64 it should be basically free.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I changed it to a std::atomic
.
Out of curiosity though: How would the race condition manifest at runtime except for the TSan failure?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would the race condition manifest at runtime except for the TSan failure?
Likely it wouldn't manifest in practice under any current compiler, but in principle it could only check the flag once and never again (for a single AST build).
c599eaf
to
3309b78
Compare
@swift-ci Please smoke test |
3309b78
to
082cea4
Compare
@swift-ci Please smoke test |
@swift-ci Please smoke test Windows |
Once this flag is set, the type checker will bail out with a “expression to complex” error.
082cea4
to
2694d0b
Compare
@swift-ci Please smoke test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically looking good, just a few minor things.
/// typechecking should be aborted at the next possible opportunity. | ||
/// This is used by SourceKit to cancel requests for which the result is no | ||
/// longer of interest. | ||
std::shared_ptr<std::atomic<bool>> CancellationFlag = nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have concerns but I've also never touched this thing 🙂 @CodaFi do you have any thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It’s a fine place to put it to start. I just hope we move off a cooperative cancellation model and push this into the request evaluator at some point.
This commit refactors the way ASTs are being built in SourceKit and how `SwiftASTConsumer`s are served by the built ASTs. `SwiftASTManager.h` should give an overview of the new design. This commit does not change the cancellation paradigm in SourceKit (yet). That is, subsequent requests with the same `OncePerASTToken` still cancel previous requests with the same token. But while previously, we were only able to cancel requests that haven’t started an AST build yet, we can now also cancel the AST build of the to-be-cancelled requests. With this change in place, we can start looking into explicit cancellation of requests or other cancellation paradigms.
2694d0b
to
7a80034
Compare
@swift-ci Please test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd still like someone other than me to comment on putting the cancellation state into the TypeCheckerOptions
. LGTM otherwise.
Seems that VS2019 and other C++ standard libraries include <atomic> as part of either <string> or <vector>, but not VS2017. When #38782 landed a new usage of std::atomic started creating compilation problems in the VS2017 builders (eg. https://ci-external.swift.org/job/oss-swift-windows-x86_64/8736/). Including the <atomic> header solves the problem.
This commit refactors the way ASTs are being built in SourceKit and how
SwiftASTConsumer
s are served by the built ASTs.SwiftASTManager.h
should give an overview of the new design.This commit does not change the cancellation paradigm in SourceKit (yet). That is, subsequent requests with the same
OncePerASTToken
still cancel previous requests with the same token. But while previously, we were only able to cancel requests that haven’t started an AST build yet, we can now also cancel the AST build of the to-be-cancelled requests.With this change in place, we can start looking into explicit cancellation of requests or other cancellation paradigms.
rdar://83391478