-
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
Ignore ALWAYS_ABORT_FLAG in count_is_zero fast path #106197
Ignore ALWAYS_ABORT_FLAG in count_is_zero fast path #106197
Conversation
Based on the assumption that always_abort usage is uncommon, change the count_is_zero() fast path to only check if GLOBAL_PANIC_COUNT is not zero, ignoring ALWAYS_ABORT_FLAG. This improves code generation for the fast path, since it no longer has to mask off the flag first. This has a small but potentially widespread impact on code quality and size, since panicking::count_is_zero() is inlined at each Mutex lock and unlock call site.
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @m-ou-se (or someone else) soon. Please see the contribution instructions for more information. |
Hey! It looks like you've submitted a new PR for the library teams! If this PR contains changes to any Examples of
|
cc @thomcc because I know we were talking about panic/aborting code paths earlier |
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.
The comment about the always abort flag a bit earlier in the file says:
Accessing LOCAL_PANIC_COUNT in a child created by
libc::fork
would lead to a memory allocation. Only GLOBAL_PANIC_COUNT can be accessed in this situation.
This PR would cause LOCAL_PANIC_COUNT to be accessed even when the always abort flag has been set.
Ah, that makes sense, thanks! |
Based on the assumption that always_abort usage is uncommon, change the count_is_zero() fast path to only check if GLOBAL_PANIC_COUNT is not zero, ignoring ALWAYS_ABORT_FLAG. This improves code generation for the fast path, since it no longer has to mask off the flag first.
This has a small but potentially widespread impact on code quality and size, since panicking::count_is_zero() is inlined at each Mutex lock and unlock call site.
Small test case that shows the improvement:
Code generation without this change (rustc 1.67.0-nightly (2585bce 2022-11-28) on x86_64 Linux (trimmed to just the fast path to highlight the changes):
The compiler backend is clever and optimizes the
& !ALWAYS_ABORT_FLAG
check into ashl ..., 1
to shift away the top bit in the lock fast path, but for some reason doesn't apply the same optimization in the unlock path (it emits amovabs
instruction with a large0x7fffffffffffffff
immediate to mask off the flag bit instead). In either case, omitting the flag check avoids an instruction or two in the critical path.With this change applied:
With this patch applied, the inlined
panicking()
function's fast path is now a load + test reg, reg + conditional jump in both the lock and unlock path.My assumption is that use of
panic::always_abort()
(#84438) is uncommon and performance is not as important in cases where it has been set; if that's not accurate, maybe this change is not a good idea, since it pessimizes the always_abort case (making it always read the thread-local panic count instead).