Skip to content

5.9: [ClosureSpecializer] Don't release trivial noescape try_apply argument twice. #66274

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

nate-chandler
Copy link
Contributor

Description: ClosureSpecializer creates releases for the closure passed as an parameter to a try_apply that is specialized. These releases are created in (1) ClosureSpecCloner::populateCloned and (2) rewriteApplyInst, depending on the effective ownership of the closure: in (1) they are inserted for closures passed without an increment of the retain count (done e.g. for closures passed as an @guaranteed parameter); in (2) they are inserted for closures passed with an increment of the retain count (done e.g. for closures passed as an @owned parameter).

Among the closures that are passed without an increment of the retain count are those which are noescape (SILFunctionType::isTrivialNoEscape). That is true even when the closure is passed as an @owned parameter. The condition of (1) under which releases are added for the closure correctly included consideration of the isTrivialNoEscape predicate of the closure's type; consequently that code inserts releases in both of the try_apply's destination blocks. The condition of (2) under which releases were added for the closure incorrectly failed to consider the isTrivialNoEscape predicate; consequently, that code also inserted releases in both of the destination blocks. The result was adding two releases in each destination block, one of each of which was an overrelease.

The fix is just to consider the isTrivialNoEscape predicate in (2).
Risk: Low. The patch adds a predicate to the bailout condition of (2) that complements an existing use of the same predicate in the condition of (1).
Scope: Narrow. This only affects releases for noescape closures passed as owned arguments to try_applys which are specialized.
Original PR: #66263
Reviewed By: Erik Eckstein ( @eeckstein ), Arnold Schwaigofer ( @aschwaighofer )
Testing: Added test case that previously inserted double release.
Resolves: rdar://110058964

When a specialization is created, in the original function, releases are
added in two different places:
(1) `ClosureSpecCloner::populateCloned`
(2) `rewriteApplyInst`

In the former, releases are added for closures which are guaranteed or
trivial noescape (but with owned convention).
In the latter, releases are added for closures that are owned.

Previously, when emitting releases at (2), whether the closure was
trivial noescape wasn't considered.  The result was inserting the
releases twice, an overrelease.

Here, fix (2) to recognize trivial noescape as not +1.

rdar://110058964
@nate-chandler nate-chandler requested a review from a team as a code owner June 1, 2023 14:35
@nate-chandler
Copy link
Contributor Author

@swift-ci please test

@nate-chandler nate-chandler merged commit 1a214ef into swiftlang:release/5.9 Jun 1, 2023
@nate-chandler nate-chandler deleted the cherrypick/release/5.9/rdar110058964 branch June 1, 2023 19:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants