Skip to content

[5.0] [silgenpattern] Fix a leak in tuple pattern emission. #21757

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
Jan 14, 2019

Conversation

gottesmm
Copy link
Contributor

Today SILGenPattern maintains the following invariants:

  1. All values passed into a switch must be either TakeAlways or BorrowAlways and
    loadable input values will be loaded.

  2. Loadable types passed to a subtree must be loaded.

  3. TakeOnSuccess can only occur with address only types and only in subtrees.

  4. A TakeOnSuccess value must go through "fake borrowing"
    (i.e. forward/unforwarding) to ensure that along failing cases, we properly
    re-enable the cleanup on the aggregate. This means that TakeOnSuccess can
    never be handled as a loadable value with ownership enabled and that any
    take_on_success value since the original cleanup on the parent value was
    disabled must be at +1.

  5. We use BorrowAlways instead of TakeOnSuccess for objects to express the
    notion that the object is not owned by the sub-tree.

The bug in this tuple code occured at the a place in the code where we go from
an address only parent type to a loadable subtype via TakeOnSuccess. I was
trying to follow (5) and thus I converted the subvalue to use a {load_borrow,
BorrowAlways}. The problem with this is that I lost the cleanup from the tuple
subvalue since take_on_success is just simulating +0 and thus entails having a
cleanup for each of the underlying tuple values.

The fix here was to:

  • Create a cleanup for the loadable subvalue leaving it in memory. This address
    version of the subvalue we use for the purposes of unforwarding. This avoids
    (4).
  • load_borrow the subvalue and pass that off to the subtree. This ensures that
    we respect (2), (3), (4).
  • Unforward in the failure case the in memory subvalue.

This gives us both characteristics as well as in the future the possibility of
enforcing via the ownership verifier that the borrow ends before the
destroy_addr.

I also sprinkled some assertions liberally to maintain invariants.

rdar://47034816
(cherry picked from commit a53e351)

Replace this paragraph with a description of your changes and rationale. Provide links to external references/discussions if appropriate.

Resolves SR-NNNN.

Today SILGenPattern maintains the following invariants:

1. All values passed into a switch must be either TakeAlways or BorrowAlways and
   loadable input values will be loaded.

2. Loadable types passed to a subtree must be loaded.

3. TakeOnSuccess can only occur with address only types and only in subtrees.

4. A TakeOnSuccess value must go through "fake borrowing"
   (i.e. forward/unforwarding) to ensure that along failing cases, we properly
   re-enable the cleanup on the aggregate. This means that TakeOnSuccess can
   never be handled as a loadable value with ownership enabled and that any
   take_on_success value since the original cleanup on the parent value was
   disabled must be at +1.

5. We use BorrowAlways instead of TakeOnSuccess for objects to express the
   notion that the object is not owned by the sub-tree.

The bug in this tuple code occured at the a place in the code where we go from
an address only parent type to a loadable subtype via TakeOnSuccess. I was
trying to follow (5) and thus I converted the subvalue to use a {load_borrow,
BorrowAlways}. The problem with this is that I lost the cleanup from the tuple
subvalue since take_on_success is just simulating +0 and thus entails having a
cleanup for each of the underlying tuple values.

The fix here was to:

* Create a cleanup for the loadable subvalue leaving it in memory. This address
  version of the subvalue we use for the purposes of unforwarding. This avoids
  (4).
* load_borrow the subvalue and pass that off to the subtree. This ensures that
  we respect (2), (3), (4).
* Unforward in the failure case the in memory subvalue.

This gives us both characteristics as well as in the future the possibility of
enforcing via the ownership verifier that the borrow ends before the
destroy_addr.

I also sprinkled some assertions liberally to maintain invariants.

rdar://47034816
(cherry picked from commit a53e351)
@gottesmm gottesmm requested a review from jckarter January 10, 2019 00:33
@gottesmm gottesmm requested a review from a team as a code owner January 10, 2019 00:33
@gottesmm
Copy link
Contributor Author

@swift-ci test

@gottesmm gottesmm changed the title [silgenpattern] Fix a leak in tuple pattern emission. [5.0] [silgenpattern] Fix a leak in tuple pattern emission. Jan 10, 2019
@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 9689ccc

@gottesmm
Copy link
Contributor Author

The test failure is from swift-5.0 using -assume-parsing-unqualified-ownership-sil instead of printing [ossa]. I put an extra commit on top of the original cherry-pick that removes that.

@gottesmm
Copy link
Contributor Author

@swift-ci test

3 similar comments
@gottesmm
Copy link
Contributor Author

@swift-ci test

@gottesmm
Copy link
Contributor Author

@swift-ci test

@gottesmm
Copy link
Contributor Author

@swift-ci test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 9689ccc

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - d604b76998562ec28bb3b02086d8f3fa14e4331a

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - d604b76998562ec28bb3b02086d8f3fa14e4331a

@gottesmm
Copy link
Contributor Author

@swift-ci test

3 similar comments
@gottesmm
Copy link
Contributor Author

@swift-ci test

@gottesmm
Copy link
Contributor Author

@swift-ci test

@gottesmm
Copy link
Contributor Author

@swift-ci test

@gottesmm
Copy link
Contributor Author

@swift-ci test os x platform

@gottesmm
Copy link
Contributor Author

@swift-ci test osx platform

@gottesmm
Copy link
Contributor Author

@swift-ci Please test OS X platform

2 similar comments
@gottesmm
Copy link
Contributor Author

@swift-ci Please test OS X platform

@gottesmm
Copy link
Contributor Author

@swift-ci Please test OS X platform

@gottesmm
Copy link
Contributor Author

I checked. The macOS test is in the queue.

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - d604b76998562ec28bb3b02086d8f3fa14e4331a

@gottesmm
Copy link
Contributor Author

Explanation: This is fixing a leak when we perform a switch on an address only tuple with a tuple element that is loadable. In SILGenPattern there are two code pathways, one for address only types that use the old logic and one for loadable types that use the new logic. This is the only place where we go from address only -> loadable. Address only code "simulates" +0 by enabling/disabling/re-enabling cleanups. Loadable types in contrast use actual +0 borrows. I needed to add a destroy cleanup (for the parent address only tuple) and then perform a load_borrow on the loadable component to get the right semantics.
Scope: This is important since it could cause leaks in programs in relatively simple code (which lead to jetsam/other badness).
SR Issue: rdar://problem/47034816
Risk: Low.
Testing: Run the compiler tests.
Reviewer: @jckarter

@eeckstein eeckstein merged commit 274c6ce into swiftlang:swift-5.0-branch Jan 14, 2019
@gottesmm gottesmm deleted the rdar47034816-5.0 branch January 14, 2019 18:32
@gottesmm
Copy link
Contributor Author

Thanks Erik!

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.

4 participants