-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
x64: Take SIGFPE signals for divide traps #6026
Conversation
Prior to this commit Wasmtime would configure `avoid_div_traps=true` unconditionally for Cranelift. This, for the division-based instructions, would change emitted code to explicitly trap on trap conditions instead of letting the `div` x86 instruction trap. There's no specific reason for Wasmtime, however, to specifically avoid traps in the `div` instruction. This means that the extra generated branches on x86 aren't necessary since the `div` and `idiv` instructions already trap for similar conditions as wasm requires. This commit instead disables the `avoid_div_traps` setting for Wasmtime's usage of Cranelift. Subsequently the codegen rules were updated slightly: * When `avoid_div_traps=true`, traps are no longer emitted for `div` instructions. * The `udiv`/`urem` instructions now list their trap as divide-by-zero instead of integer overflow. * The lowering for `sdiv` was updated to still explicitly check for zero but the integer overflow case is deferred to the instruction itself. * The lowering of `srem` no longer checks for zero and the listed trap for the `div` instruction is a divide-by-zero. This means that the codegen for `udiv` and `urem` no longer have any branches. The codegen for `sdiv` removes one branch but keeps the zero-check to differentiate the two kinds of traps. The codegen for `srem` removes one branch but keeps the -1 check since the semantics of `srem` mismatch with the semantics of `idiv` with a -1 divisor (specifically for INT_MIN). This is unlikely to have really all that much of a speedup but was something I noticed during bytecodealliance#6008 which seemed like it'd be good to clean up. Plus Wasmtime's signal handling was already set up to catch `SIGFPE`, it was just never firing.
Subscribe to Label Actioncc @peterhuene
This issue or pull request has been labeled: "cranelift", "cranelift:area:x64", "wasmtime:api"
Thus the following users have been cc'd because of the following labels:
To subscribe or unsubscribe from this label, edit the |
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.
A thought on the plumbing below; also, if you want to branch-fold away the avoid_div_traps=true
case as part of this PR or a followup, I think that would also be a welcome change (unless there's an environment where it is necessary that I'm missing).
With no known users currently removing this should be possible and helps simplify the x64 backend.
Remove the `validate_sdiv_divisor*` pseudo-instructions and clean up some of the ISLE rules now that `div` is allowed to itself trap unconditionally.
Nah I think it makes sense to go ahead and do that here, and I feel it pretty nicely simplified the rules! |
One minor non-optimal bit about this PR is that currently I've represented the trap as |
Don't accidentally fold multiple traps together
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.
Thanks for the updates! Non-optional trapcode is fine, IMHO; we can always optimize later as you say.
r+ with CI fix (emit-tests that need to be updated with the new trapcode parameter)
After upgrading to Wasmtime 8.0.0, how can we revert back to the previous behavior? This patch causes Valgrind to complain about SIGFPE when before 8.0.0 everything was just fine. Just to be clear we don't want to raise SIGFPE when Wasmtime encounters a div by 0, we want it to throw a trap as usual and nothing more. |
@thibaultcha there isn't really a good way to do that; this PR removed the code-paths that support inline checks rather than relying on signals, because it vastly simplifies things and we judged that it would be fine to use SIGFPE handling instead for the embedding scenarios we support. It's possible we could revert this whole PR, but that does have a maintenance cost, so it would be useful to know more about the requirements of your case. Is the issue mainly Valgrind warnings (and if so, is there a way to define a suppression for them)? Or is there something more fundamental about your embedding environment where signals are not acceptable? |
Out of curiosity, if SIGFPE is causing problems how does valgrind handle wasm performing out-of-bounds memory loads? Those are done with guard pages and signal handling right now, so if those are working then I'd expecte SIGFPE to work as well. Or are you perhaps configuring wasm to have no signals by using dynamic memory with explicit bounds checks? (I'm also curious about what Chris mentioned in terms of suppressions and info about signals, too) |
It seems we have sorted it out! It wasn't my intention to ask for a revert this patch; it was rather that since I read:
I was initially wondering if we as users could revert this setting to get back to the previous behavior and fix our issue. We found that a Valgrind flag does the trick for this test and allows us to correctly handle SIGFPE with the new cranelift behavior: Thank you both for the replies! |
Great! I'm glad you've got a solution and let us know if you have any other issues. We're always happy to take PRs to docs if you feel like there's a place where a Valgrind-related tip might have helped you (but no pressure at all, of course); otherwise at least these comments should be searchable if others hit the same thing in the future. |
Prior to this commit Wasmtime would configure
avoid_div_traps=true
unconditionally for Cranelift. This, for the division-based instructions, would change emitted code to explicitly trap on trap conditions instead of letting thediv
x86 instruction trap.There's no specific reason for Wasmtime, however, to specifically avoid traps in the
div
instruction. This means that the extra generated branches on x86 aren't necessary since thediv
andidiv
instructions already trap for similar conditions as wasm requires.This commit instead disables the
avoid_div_traps
setting for Wasmtime's usage of Cranelift. Subsequently the codegen rules were updated slightly:avoid_div_traps=true
, traps are no longer emitted fordiv
instructions.udiv
/urem
instructions now list their trap as divide-by-zero instead of integer overflow.sdiv
was updated to still explicitly check for zero but the integer overflow case is deferred to the instruction itself.srem
no longer checks for zero and the listed trap for thediv
instruction is a divide-by-zero.This means that the codegen for
udiv
andurem
no longer have any branches. The codegen forsdiv
removes one branch but keeps the zero-check to differentiate the two kinds of traps. The codegen forsrem
removes one branch but keeps the -1 check since the semantics ofsrem
mismatch with the semantics ofidiv
with a -1 divisor (specifically for INT_MIN).This is unlikely to have really all that much of a speedup but was something I noticed during #6008 which seemed like it'd be good to clean up. Plus Wasmtime's signal handling was already set up to catch
SIGFPE
, it was just never firing.