Skip to content

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

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

gottesmm
Copy link
Contributor

@gottesmm gottesmm commented Jan 9, 2019

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

@gottesmm
Copy link
Contributor Author

gottesmm commented Jan 9, 2019

@swift-ci test

@slavapestov
Copy link
Contributor

(I'm going to punt this review to @jckarter and @rjmccall because I can't pretend to understand the algorithm here well enough and I don't have cycles at this moment to familiarize myself with the code)

@gottesmm gottesmm removed the request for review from slavapestov January 9, 2019 21:05
Copy link
Contributor

@jckarter jckarter left a comment

Choose a reason for hiding this comment

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

Michael talked me through this in person. LGTM.

@gottesmm
Copy link
Contributor Author

gottesmm commented Jan 9, 2019

JoeG asked me to fix this comment:

https://github.com/apple/swift/pull/21745/files#diff-95c4d5d527b6ea06630be4cf0edd94f3R1550

I am going to fix that and then do a smoke test/merge since I already did a full test.

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
@gottesmm gottesmm force-pushed the pr-7badf1ef083f46a99dde5777619f7f410168e8a5 branch from aa331d2 to a53e351 Compare January 9, 2019 23:14
@gottesmm
Copy link
Contributor Author

gottesmm commented Jan 9, 2019

@swift-ci smoke test and merge

2 similar comments
@gottesmm
Copy link
Contributor Author

gottesmm commented Jan 9, 2019

@swift-ci smoke test and merge

@gottesmm
Copy link
Contributor Author

gottesmm commented Jan 9, 2019

@swift-ci smoke test and merge

@swift-ci swift-ci merged commit 749f319 into swiftlang:master Jan 10, 2019
@gottesmm gottesmm deleted the pr-7badf1ef083f46a99dde5777619f7f410168e8a5 branch January 10, 2019 00:29
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