-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Nonzeroing Move Hints (take3 branch) #26173
Conversation
r? @Aatch (rust_highfive has picked a reviewer for you, use r? to override) |
Note: I am still putting this branch through its paces locally. My most recent
Not sure yet what is up with that; it could be a latent bug in my PR, or some other bad interaction. In any case, I wanted to put this up for some preliminary review; I suspect that even if we cannot land the whole PR yet, some of the earlier commits that refactor the code may be worth landing on their own. |
❗ |
(i'm sure people are curious about performance results too. I can work on posting some numbers once I regather them, but the expectation based on my earlier measurements is that this yields somewhere between a 2% and 5% improvement in compilation time. It is not 100% clear where the improvement is coming from; that is, I had thought we would be able to clearly associate the improvement with one factor like "LLVM is spending less time trying to optimize code") |
(I do want to read over @eefriedman 's alternative approach to removing drop flags, at eefriedman:dynamic-drop ; but I wanted to get this up first since as I said it has some changes that may want to land regardless of what overall strategy we adopt.) |
cc @carllerche |
The There is not a 100% clear smoking gun from the debugger backtraces, however. Most of the backtraces look like this:
but there were two that looked like this:
and then there was another that looked like this:
(Its certainly possible that one of the cases that is marked as |
4ff13a3
to
7d7dbcb
Compare
@pnkfelix did you observe an improvement in execution time as well? I cannot recall :) |
// FIXME (#5016): pnkfelix is not 100% sure how we are | ||
// going handle this long-term. Maybe easiest to just | ||
// not allow arguments that are Drop to be passed | ||
// indirectly. |
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.
If the caller is trying to drop the alloca used for an indirect argument, that's a bug. They shouldn't be touched at all after a call because the callee is guaranteed to drop them. (At least, that's how I understand the current model.)
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.
Yes, that is correct. The callee owns the value, they can move it, drop it, etc.
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.
Okay, I'll see if I can properly encode this and avoid the ZeroAndMaintain
here in that case. (But first I want to fix the bugs i am observing with this branch as it stands...)
☔ The latest upstream changes (presumably #26190) made this pull request unmergeable. Please resolve the merge conflicts. |
This looks good to me. |
(note that there is still that bug I need to resolve, noted above) |
Two weeks later: After some more investigation (that was interrupted several time for long stretches), I am pretty confident that the only bugs left to resolve are poor interactions with the drop-flag sanity checking that I put in. In other words, if I cannot resolve those interactions quickly, then I will be happy to simply remove the sanity checking, and get this landed. |
451b524
to
29ab769
Compare
29ab769
to
c0e4e95
Compare
r+ modulo comments and nits. |
…hInput` rather than `ValueRef`. (already thumbs-upped pre-rebase by nikomatsakis) The refactoring here is trivial because `trans::datum::Lvalue` currently carries no payload. However, future commits will start adding a payload to `Lvalue`, and thus will force us either 1. to thread the payload through the `_match` code (a long term goal), or 2. to ensure the payload has some reasonable default value.
(already thumbs-upped pre-rebase by nikomatsakis)
…hint. Instrumented calls sites that construct Lvalues to ease tracking down cases that we might need to change whether or not they carry a hint. Note that this commit does not do anything to actually *construct* the `lldropflag_hints` map, nor does it change anything about codegen itself. Those parts are in follow-on commits.
…rans. Added code to maintain these hints at runtime, and to conditionalize drop-filling and calls to destructors. In this early stage, we are using hints, so we are always free to leave out a flag for a path -- then we just pass `None` as the dropflag hint in the corresponding schedule cleanup call. But, once a path has a hint, we must at least maintain it: i.e. if the hint exists, we must ensure it is never set to "moved" if the data in question might actually have been initialized. It remains sound to conservatively set the hint to "initialized" as long as the true drop-flag embedded in the value itself is up-to-date. ---- Here are some high-level details I want to point out: * We maintain the hint in Lvalue::post_store, marking the lvalue as moved. (But also continue drop-filling if necessary.) * We update the hint on ExprAssign. * We pass along the hint in once closures that capture-by-move. * You only call `drop_ty` for state that does not have an associated hint. If you have a hint, you must call `drop_ty_core` instead. (Originally I passed the hint into `drop_ty` as well, to make the connection to a hint more apparent, but the vast majority of current calls to `drop_ty` are in contexts where no hint is available, so it just seemed like noise in the resulting diff.)
Testing indicates bug would have been caught, albeit later than one might hope, during `sync::mpsc::tests::smoke_shared_port_gone2` test.
…lling drop is in use.
Updated all call sites that used the other contructors to uniformly call `Lvalue::new_with_hint`, passing along the appropriate kind of hint for each context. Placated tidy in a few other places in datum.rs.
c0e4e95
to
b4dd765
Compare
@bors r=nikomatsakis |
📌 Commit b4dd765 has been approved by |
Add dropflag hints (stack-local booleans) for unfragmented paths in trans. Part of #5016. Added code to maintain these hints at runtime, and to conditionalize drop-filling and calls to destructors. In this early stage of my incremental implementation strategy, we are using hints, so we are always free to leave out a flag for a path -- then we just pass `None` as the dropflag hint in the corresponding schedule cleanup call. But, once a path has a hint, we must at least maintain it: i.e. if the hint exists, we must ensure it is never set to "moved" if the data in question might actually have been initialized. It remains sound to conservatively set the hint to "initialized" as long as the true drop-flag embedded in the value itself is up-to-date. I hope the commit series has been broken up to be readable; most of the commits in the series should build (though I did not always check this). ---- Oh, I think this technically qualifies as a: [breaking-change] because it removes drop-filling in some cases where one could previously observe it. That should only affect `unsafe` code; no safe code should be able to inspect whether the drop-fill was present or not. For an example of code that needed to change to account for this, see commit a81c24ae0216ab47df59acd724f8a33124fb6d97 (a unit test of the `move_val_init` intrinsic). I have not encountered actual code that needed to be updated to account for the change, since this should only be skipping the drop-filling on *moved* values, not on dropped one, and so even types that use `unsafe_no_drop_flag` should be unchanged by this particular PR. (Their time will come later.)
🎊 💖 ✨ |
This is a temporary workaround for the bugs that have been found in the implementation of PR rust-lang#26173. * pnkfelix is unavailable in the short-term (i.e. for the next week) to fix them. * When the bugs are fixed, we will turn this back on by default. (If you want to play with the known-to-be-buggy optimization in the meantime, you can opt-back in via the debugging option that this commit is toggling.)
This is a temporary workaround for the bugs that have been found in the implementation of PR rust-lang#26173. * pnkfelix is unavailable in the short-term (i.e. for the next week) to fix them. * When the bugs are fixed, we will turn this back on by default. (If you want to play with the known-to-be-buggy optimization in the meantime, you can opt-back in via the debugging option that this commit is toggling.)
This is a temporary workaround for the bugs that have been found in the implementation of PR rust-lang#26173. * pnkfelix is unavailable in the short-term (i.e. for the next week) to fix them. * When the bugs are fixed, we will turn this back on by default. (If you want to play with the known-to-be-buggy optimization in the meantime, you can opt-back in via the debugging option that this commit is toggling.)
Add dropflag hints (stack-local booleans) for unfragmented paths in trans. Part of #5016.
Added code to maintain these hints at runtime, and to conditionalize drop-filling and calls to destructors.
In this early stage of my incremental implementation strategy, we are using hints, so we are always free to leave out a flag for a path -- then we just pass
None
as the dropflag hint in the corresponding schedule cleanup call. But, once a path has a hint, we must at least maintain it: i.e. if the hint exists, we must ensure it is never set to "moved" if the data in question might actually have been initialized. It remains sound to conservatively set the hint to "initialized" as long as the true drop-flag embedded in the value itself is up-to-date.I hope the commit series has been broken up to be readable; most of the commits in the series should build (though I did not always check this).
Oh, I think this technically qualifies as a:
[breaking-change]
because it removes drop-filling in some cases where one could previously observe it. That should only affect
unsafe
code; no safe code should be able to inspect whether the drop-fill was present or not. For an example of code that needed to change to account for this, see commit a81c24ae0216ab47df59acd724f8a33124fb6d97 (a unit test of themove_val_init
intrinsic). I have not encountered actual code that needed to be updated to account for the change, since this should only be skipping the drop-filling on moved values, not on dropped one, and so even types that useunsafe_no_drop_flag
should be unchanged by this particular PR. (Their time will come later.)