Skip to content

Add SIL Pass for flow-sensitive, region-based Sendable checking #67172

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

Merged
merged 3 commits into from
Jul 11, 2023

Conversation

JTurcotti
Copy link
Contributor

@JTurcotti JTurcotti commented Jul 6, 2023

Under current strict concurrency checking, function calls that will execute in a different isolation domain than the caller are not allowed to be passed values whose type does not conform to the Sendable protocol. This model is difficult to code under, and is overly restrictive: values of arbitrary type may be safely passed to other isolation domains provided they are not aliased or otherwise accessed afterwards.

This PR begins to implement a SIL pass that performs flow-sensitive checking to allow safe passing of non-Sendable values between isolation domains. Statically, values are grouped into "regions". Values in the same region may alias or point to each other in the heap, but values in different regions are guaranteed to be mutually inaccessible. A linear type system then tracks the regions that are accessible - marking regions "consumed" when any of their values are sent to other isolation domains. This is necessarily still an over-approximation - dynamically, it may be possible two values in the same region have nothing to do with each other - but still enables a much wider variety of local concurrent programming patterns than previously possible.

At an implementation level, the key object is the Partition datatype defined in PartitionUtils.h. The PartitionAnalysis engine in SendNonSendable.cpp then implements an analysis that uses these partitions to divide all SILValues into the regions described above, consuming the regions when they are sent to other isolation domains and throwing diagnostics when values from a consumed region are accessed. To accomplish this, a PartitionOpTranslator translates sequences of SILInstructions into sequences of PartitionOps. PartitionOps describe primitive transformations to the partition such as assigning indices to new regions, assigning indices to existing regions, merging regions, consuming regions, and requiring the existence of regions. Though it is not yet tested in this PR, the translation into PartitionOps is followed by a fixpoint iteration algorithm that solves for the partitions at exit and entry to each basic block that respect the action of the generated PartitionOps, and respect the structure of the CFG.

region_based_sendability.swift contains test cases highlighting the key functionality of this PR. Much more functionality, such as testing more general control flow, is not yet tested, but will be in followup PRs. Even more functionality, such as handling defer blocks and handling other concurrency primitives besides plain async/await, is not yet implemented and will also come in followup PRs.

@JTurcotti
Copy link
Contributor Author

@swift-ci please smoke test

jturcotti added 2 commits July 10, 2023 15:20
…g a partition data structure that will be used for flow-sensitive, region-based Sendable checking.
…is engine, works for some simple examples but needs to address address values in SIL.
@JTurcotti JTurcotti changed the title [Draft] Add SIL Pass for intelligent Sendable checking Add SIL Pass for flow-sensitive, region-based Sendable checking Jul 10, 2023
@JTurcotti
Copy link
Contributor Author

@swift-ci please smoke test

@JTurcotti JTurcotti marked this pull request as ready for review July 10, 2023 22:35
@kavon kavon requested a review from atrick July 11, 2023 17:55
… comprehensive suite of simple tests passes (region_based_sendability.swift)
@JTurcotti
Copy link
Contributor Author

@swift-ci please smoke test

Comment on lines +862 to +864
"Non-Sendable value consumed, then used at this site; could yield race with another thread", ())
WARNING(arg_region_consumed, none,
"This application could pass `self` or a Non-Sendable argument of this function to another thread, potentially yielding a race with the caller", ())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

small note: we usually don't capitalize the first letter of diagnostics unlesss its proper noun. Also would be good to avoid the "consume" terminology since we use that for move-only types. Perhaps we can call these actions "transfers" of non-sendable values that are causing the uses afterwards to be illegal.

@JTurcotti JTurcotti merged commit e811193 into swiftlang:main Jul 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants