Closed
Bug 1268910
Opened 9 years ago
Closed 8 years ago
Baldr: trap on edge cases for arithmetic operations
Categories
(Core :: JavaScript Engine: JIT, defect)
Core
JavaScript Engine: JIT
Tracking
()
RESOLVED
FIXED
People
(Reporter: bbouvier, Assigned: bbouvier)
References
Details
Attachments
(5 files, 3 obsolete files)
13.61 KB,
patch
|
luke
:
review+
|
Details | Diff | Splinter Review |
32.87 KB,
patch
|
sunfish
:
review+
|
Details | Diff | Splinter Review |
5.26 KB,
patch
|
luke
:
review+
|
Details | Diff | Splinter Review |
19.04 KB,
patch
|
luke
:
review+
|
Details | Diff | Splinter Review |
6.38 KB,
patch
|
sunfish
:
review+
|
Details | Diff | Splinter Review |
e.g. I32Div should trap when we try to divide by zero.
We should also find a way to generalize traps, so we don't have to create a stub for each of them, and just generate a reason that we pass to the trap handler.
Assignee | ||
Comment 1•9 years ago
|
||
Just asking feedback at the moment, to validate the approach. I don't think it's fine to generate an error stub inline, so instead we could have a JumpTarget::Trap, and we'd push the reason onto the stack first in MacroAssembler::wasmTrap; and would read it from the error stub (that is, the target of JumpTarget::Trap) later. How does that sound?
Attachment #8747110 -
Flags: feedback?(luke)
Comment 2•9 years ago
|
||
Comment on attachment 8747110 [details] [diff] [review]
traps wip
Review of attachment 8747110 [details] [diff] [review]:
-----------------------------------------------------------------
Yes, this definitely looks good! IIUC, you're saying the patch would *not* use callWithABI which I think is good b/c I think it doesn't work for wasm (in particular, wrt profiling).
Attachment #8747110 -
Flags: feedback?(luke) → feedback+
Assignee | ||
Comment 3•9 years ago
|
||
Attachment #8747110 -
Attachment is obsolete: true
Attachment #8747768 -
Flags: review?(luke)
Assignee | ||
Comment 4•9 years ago
|
||
And this is what it looks like to add a new trap thereafter.
Comment 5•9 years ago
|
||
Comment on attachment 8747768 [details] [diff] [review]
traps.patch
Review of attachment 8747768 [details] [diff] [review]:
-----------------------------------------------------------------
::: js/src/asmjs/WasmStubs.cpp
@@ +869,5 @@
> +
> + // sp can be anything at this point, so ensure it is aligned when calling
> + // into C++. We unconditionally jump to throw so don't worry about
> + // restoring sp.
> + masm.andToStackPtr(Imm32(~(ABIStackAlignment - 1)));
Pre-existing from GenerateErrorStub (which I'm hoping we can wholly replace by this function), but I think, after masking the stack pointer, you need to further subtract ShadowStackSpace (which is bytes above the stack pointer that may be clobbered by the callee). (See GenerateInterruptStub.)
@@ +879,5 @@
> + if (i->kind() == ABIArg::GPR) {
> + if (WasmTrapStubArgReg != i->gpr())
> + masm.move32(WasmTrapStubArgReg, i->gpr());
> + } else {
> + masm.storePtr(WasmTrapStubArgReg,
I think this should be store32.
@@ +937,5 @@
> return GenerateErrorStub(masm, SymbolicAddress::OnOutOfBounds);
> case JumpTarget::BadIndirectCall:
> return GenerateErrorStub(masm, SymbolicAddress::BadIndirectCall);
> + case JumpTarget::Trap:
> + return GenerateTrapStub(masm);
Can you use GenerateTrapStub for the other two as well, removing GenerateErrorStub?
::: js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp
@@ +2577,5 @@
>
> + Label done;
> + if (gen->compilingAsmJS()) {
> + masm.j(Assembler::Equal, &done);
> + masm.wasmTrap(wasm::Trap::ImpreciseSimdConversion);
Can you give wasmTrap a condition? Otherwise, this change deoptimizes the common case where there is no trap.
Attachment #8747768 -
Flags: review?(luke) → review+
Assignee | ||
Comment 6•9 years ago
|
||
Thank you for the review!
(In reply to Luke Wagner [:luke] from comment #5)
> Comment on attachment 8747768 [details] [diff] [review]
> traps.patch
>
> Review of attachment 8747768 [details] [diff] [review]:
> -----------------------------------------------------------------
>
> ::: js/src/asmjs/WasmStubs.cpp
> @@ +869,5 @@
> > +
> > + // sp can be anything at this point, so ensure it is aligned when calling
> > + // into C++. We unconditionally jump to throw so don't worry about
> > + // restoring sp.
> > + masm.andToStackPtr(Imm32(~(ABIStackAlignment - 1)));
>
> Pre-existing from GenerateErrorStub (which I'm hoping we can wholly replace
> by this function), but I think, after masking the stack pointer, you need to
> further subtract ShadowStackSpace (which is bytes above the stack pointer
> that may be clobbered by the callee). (See GenerateInterruptStub.)
Ha! Could it be somehow related to bug 1267441, which happens only on win x64, which iirc is the only platform that has shadow stack space? The out of memory stub uses the GenerateErrorStub, so maybe the stack gets corrupted after the call and we don't jump to the throw handler, or go there with a stack that sometimes is wrong?
> @@ +937,5 @@
> > return GenerateErrorStub(masm, SymbolicAddress::OnOutOfBounds);
> > case JumpTarget::BadIndirectCall:
> > return GenerateErrorStub(masm, SymbolicAddress::BadIndirectCall);
> > + case JumpTarget::Trap:
> > + return GenerateTrapStub(masm);
>
> Can you use GenerateTrapStub for the other two as well, removing
> GenerateErrorStub?
I've tried this first, but the stubs entries are directly referenced from inline code (e.g. the out of bounds stubs is the one we redirect to from the OOB signal handler, for OOB SIMD accesses), and it makes things more complicated. I can look into it in another patch, though.
>
> ::: js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp
> @@ +2577,5 @@
> >
> > + Label done;
> > + if (gen->compilingAsmJS()) {
> > + masm.j(Assembler::Equal, &done);
> > + masm.wasmTrap(wasm::Trap::ImpreciseSimdConversion);
>
> Can you give wasmTrap a condition? Otherwise, this change deoptimizes the
> common case where there is no trap.
I've done that: although there is no Assembler::Condition::Always on x86 and x64, so I made two variants (one with Assembler::Condition, one without it).
Comment 7•9 years ago
|
||
Actually, now that I think about it, wasmTrap() would be more flexible if, in addition taking a Condition, it was a single conditional-branch instruction. Otherwise you can't use the branch to either jump-to-trap or fallthrough-to-valid since the move is executed either way. Rather, I think there should be 1 jump target per trap and each jump target stores the Trap code and calls a single C++ function.
Assignee | ||
Comment 8•9 years ago
|
||
Agreed on irc that the required changes are bigger than expected so another look would be good.
Attachment #8747768 -
Attachment is obsolete: true
Attachment #8748253 -
Flags: review?(luke)
Assignee | ||
Comment 9•9 years ago
|
||
This implements the traps on integer (signed or unsigned) div/mod:
- div/mod by zero
- div INTMIN by -1
As far as I can tell from the tests, there are no other traps for any arithmetic operations, be it on integers or non-integer operations: is that correct?
With this patch, the spec test i32.wast passes in our implementation.
Attachment #8747769 -
Attachment is obsolete: true
Attachment #8748258 -
Flags: review?(sunfish)
Comment 10•9 years ago
|
||
Comment on attachment 8748258 [details] [diff] [review]
trap-div-mod.patch
Review of attachment 8748258 [details] [diff] [review]:
-----------------------------------------------------------------
Looks good!
Attachment #8748258 -
Flags: review?(sunfish) → review+
Comment 11•9 years ago
|
||
Comment on attachment 8748253 [details] [diff] [review]
traps.patch
Review of attachment 8748253 [details] [diff] [review]:
-----------------------------------------------------------------
Great, thanks!
::: js/src/asmjs/WasmStubs.cpp
@@ +869,5 @@
> + // into C++. We unconditionally jump to throw so don't worry about
> + // restoring sp.
> + masm.andToStackPtr(Imm32(~(ABIStackAlignment - 1)));
> + if (ShadowStackSpace)
> + masm.subFromStackPtr(Imm32(ShadowStackSpace));
Could you fix up GenerateErrorStub as well?
Attachment #8748253 -
Flags: review?(luke) → review+
Assignee | ||
Comment 12•9 years ago
|
||
Actually the OOB stub is trivial to remove.
Attachment #8748574 -
Flags: review?(luke)
Comment 13•9 years ago
|
||
Comment on attachment 8748574 [details] [diff] [review]
oobstub.patch
Review of attachment 8748574 [details] [diff] [review]:
-----------------------------------------------------------------
Great!
::: js/src/asmjs/WasmStubs.cpp
@@ +935,2 @@
> case JumpTarget::BadIndirectCall:
> return GenerateErrorStub(masm, SymbolicAddress::BadIndirectCall);
Ah, and this straggler will probably get removed or rejiggered with the heterogeneous table work.
::: js/src/asmjs/WasmTypes.h
@@ +643,5 @@
> // Integer division by zero.
> IntegerDivideByZero,
>
> + // (asm.js only) out of bounds on SIMD and atomic memory accesses.
> + OutOfBounds,
This will be exercised by wasm load/store oob too, so I'd tweak the comment and put it up with the others.
Attachment #8748574 -
Flags: review?(luke) → review+
Assignee | ||
Comment 14•9 years ago
|
||
As said on IRC, I'm worried about one thing: if we call from an inline stub we can jump to, will profiling work? Testing suggests it does, but this might be our tests don't cover this.
Attachment #8748654 -
Flags: review?(luke)
Comment 15•9 years ago
|
||
Comment on attachment 8748654 [details] [diff] [review]
badindirectcall.patch
Review of attachment 8748654 [details] [diff] [review]:
-----------------------------------------------------------------
Even better! Good observation.
::: js/src/asmjs/WasmTypes.h
@@ +648,2 @@
> // (asm.js only) out of bounds on SIMD and atomic memory accesses.
> OutOfBounds,
In my previous comment, I didn't mean that the whole error would go away, just how we exercise it. I think the target impl scheme will be to check the signature in the callee which will jump to this same stub. So I don't think it's (temporary) and I'd give it a proper comment and move it up with the others.
Attachment #8748654 -
Flags: review?(luke) → review+
Assignee | ||
Comment 16•9 years ago
|
||
And an addendum, so that unsigned div/mod by zero don't get constant folded into the wrong thing. This also adds tests so that i32 edge cases are handled for the constant value cases; in particular, this ensures that div_s/mod_s are not getting DCE'd.
Attachment #8750297 -
Flags: review?(sunfish)
Comment 17•9 years ago
|
||
Assignee | ||
Updated•9 years ago
|
Keywords: leave-open
Comment 18•9 years ago
|
||
Comment 19•9 years ago
|
||
bugherder |
Comment 20•9 years ago
|
||
Comment on attachment 8750297 [details] [diff] [review]
addendum.patch
Review of attachment 8750297 [details] [diff] [review]:
-----------------------------------------------------------------
Looks good.
Attachment #8750297 -
Flags: review?(sunfish) → review+
Comment 21•9 years ago
|
||
Comment 22•9 years ago
|
||
bugherder |
Assignee | ||
Comment 23•8 years ago
|
||
Forgot to remove leave-open after the last push.
You need to log in
before you can comment on or make changes to this bug.
Description
•