Bug 1428453 - Baldr: use new traps for idiv (r=bbouvier)

--HG--
extra : rebase_source : 530b9de9df9dfab1a3db688156c04d1c97cc9158
This commit is contained in:
Luke Wagner 2018-02-12 15:30:46 -06:00
parent 3c79523451
commit 363c35ecbf
11 changed files with 102 additions and 34 deletions

View File

@ -554,7 +554,10 @@ CodeGeneratorARM::divICommon(MDiv* mir, Register lhs, Register rhs, Register out
masm.as_cmp(rhs, Imm8(0));
if (mir->canTruncateInfinities()) {
if (mir->trapOnError()) {
masm.ma_b(oldTrap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Equal);
Label nonZero;
masm.ma_b(&nonZero, Assembler::NotEqual);
masm.wasmTrap(wasm::Trap::IntegerDivideByZero, mir->bytecodeOffset());
masm.bind(&nonZero);
} else {
// Infinity|0 == 0
Label skip;
@ -717,7 +720,10 @@ CodeGeneratorARM::modICommon(MMod* mir, Register lhs, Register rhs, Register out
// wasm allows negative lhs and return 0 in this case.
MOZ_ASSERT(mir->isTruncated());
masm.as_cmp(rhs, Imm8(0));
masm.ma_b(oldTrap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Equal);
Label nonZero;
masm.ma_b(&nonZero, Assembler::NotEqual);
masm.wasmTrap(wasm::Trap::IntegerDivideByZero, mir->bytecodeOffset());
masm.bind(&nonZero);
return;
}
@ -2420,7 +2426,10 @@ CodeGeneratorARM::generateUDivModZeroCheck(Register rhs, Register output, Label*
masm.as_cmp(rhs, Imm8(0));
if (mir->isTruncated()) {
if (mir->trapOnError()) {
masm.ma_b(oldTrap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Equal);
Label nonZero;
masm.ma_b(&nonZero, Assembler::NotEqual);
masm.wasmTrap(wasm::Trap::IntegerDivideByZero, mir->bytecodeOffset());
masm.bind(&nonZero);
} else {
Label skip;
masm.ma_b(&skip, Assembler::NotEqual);
@ -2770,8 +2779,10 @@ CodeGeneratorARM::visitDivOrModI64(LDivOrModI64* lir)
// Handle divide by zero.
if (lir->canBeDivideByZero()) {
Register temp = WasmGetTemporaryForDivOrMod(lhs, rhs);
masm.branchTest64(Assembler::Zero, rhs, rhs, temp,
oldTrap(lir, wasm::Trap::IntegerDivideByZero));
Label nonZero;
masm.branchTest64(Assembler::NonZero, rhs, rhs, temp, &nonZero);
masm.wasmTrap(wasm::Trap::IntegerDivideByZero, lir->bytecodeOffset());
masm.bind(&nonZero);
}
auto* mir = lir->mir();
@ -2816,8 +2827,10 @@ CodeGeneratorARM::visitUDivOrModI64(LUDivOrModI64* lir)
// Prevent divide by zero.
if (lir->canBeDivideByZero()) {
Register temp = WasmGetTemporaryForDivOrMod(lhs, rhs);
masm.branchTest64(Assembler::Zero, rhs, rhs, temp,
oldTrap(lir, wasm::Trap::IntegerDivideByZero));
Label nonZero;
masm.branchTest64(Assembler::NonZero, rhs, rhs, temp, &nonZero);
masm.wasmTrap(wasm::Trap::IntegerDivideByZero, lir->bytecodeOffset());
masm.bind(&nonZero);
}
masm.setupWasmABICall();

View File

@ -1725,7 +1725,7 @@ MacroAssembler::branchTest64(Condition cond, Register64 lhs, Register64 rhs, Reg
{
ScratchRegisterScope scratch(*this);
if (cond == Assembler::Zero) {
if (cond == Assembler::Zero || cond == Assembler::NonZero) {
MOZ_ASSERT(lhs.low == rhs.low);
MOZ_ASSERT(lhs.high == rhs.high);
ma_orr(lhs.low, lhs.high, scratch);

View File

@ -568,7 +568,10 @@ CodeGeneratorMIPSShared::visitDivI(LDivI* ins)
// Handle divide by zero.
if (mir->canBeDivideByZero()) {
if (mir->trapOnError()) {
masm.ma_b(rhs, rhs, oldTrap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
Label nonZero;
masm.ma_b(rhs, rhs, &nonZero, Assembler::NonZero);
masm.wasmTrap(wasm::Trap::IntegerDivideByZero, mir->bytecodeOffset());
masm.bind(&nonZero);
} else if (mir->canTruncateInfinities()) {
// Truncated division by zero is zero (Infinity|0 == 0)
Label notzero;
@ -721,7 +724,10 @@ CodeGeneratorMIPSShared::visitModI(LModI* ins)
if (mir->canBeDivideByZero()) {
if (mir->isTruncated()) {
if (mir->trapOnError()) {
masm.ma_b(rhs, rhs, oldTrap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
Label nonZero;
masm.ma_b(rhs, rhs, &nonZero, Assembler::NonZero);
masm.wasmTrap(wasm::Trap::IntegerDivideByZero, mir->bytecodeOffset());
masm.bind(&nonZero);
} else {
Label skip;
masm.ma_b(rhs, Imm32(0), &skip, Assembler::NotEqual, ShortJump);
@ -2395,7 +2401,10 @@ CodeGeneratorMIPSShared::visitUDivOrMod(LUDivOrMod* ins)
if (ins->canBeDivideByZero()) {
if (ins->mir()->isTruncated()) {
if (ins->trapOnError()) {
masm.ma_b(rhs, rhs, oldTrap(ins, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
Label nonZero;
masm.ma_b(rhs, rhs, &nonZero, Assembler::NonZero);
masm.wasmTrap(wasm::Trap::IntegerDivideByZero, ins->bytecodeOffset());
masm.bind(&nonZero)
} else {
// Infinity|0 == 0
Label notzero;

View File

@ -379,8 +379,12 @@ CodeGeneratorMIPS::visitDivOrModI64(LDivOrModI64* lir)
Label done;
// Handle divide by zero.
if (lir->canBeDivideByZero())
masm.branchTest64(Assembler::Zero, rhs, rhs, temp, oldTrap(lir, wasm::Trap::IntegerDivideByZero));
if (lir->canBeDivideByZero()) {
Label nonZero;
masm.branchTest64(Assembler::NonZero, rhs, rhs, temp, &nonZero);
masm.wasmTrap(wasm::Trap::IntegerDivideByZero, lir->bytecodeOffset());
masm.bind(&nonZero);
}
// Handle an integer overflow exception from INT64_MIN / -1.
if (lir->canBeNegativeOverflow()) {
@ -431,8 +435,12 @@ CodeGeneratorMIPS::visitUDivOrModI64(LUDivOrModI64* lir)
Register temp = regs.takeAny();
// Prevent divide by zero.
if (lir->canBeDivideByZero())
masm.branchTest64(Assembler::Zero, rhs, rhs, temp, oldTrap(lir, wasm::Trap::IntegerDivideByZero));
if (lir->canBeDivideByZero()) {
Label nonZero;
masm.branchTest64(Assembler::NonZero, rhs, rhs, temp, &nonZero);
masm.wasmTrap(wasm::Trap::IntegerDivideByZero, lir->bytecodeOffset());
masm.bind(&nonZero);
}
masm.setupWasmABICall();
masm.passABIArg(lhs.high);

View File

@ -361,8 +361,12 @@ CodeGeneratorMIPS64::visitDivOrModI64(LDivOrModI64* lir)
Label done;
// Handle divide by zero.
if (lir->canBeDivideByZero())
masm.ma_b(rhs, rhs, oldTrap(lir, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
if (lir->canBeDivideByZero()) {
Label nonZero;
masm.ma_b(rhs, rhs, &nonZero, Assembler::NonZero);
masm.wasmTrap(wasm::Trap::IntegerDivideByZero, lir->bytecodeOffset());
masm.bind(&nonZero);
}
// Handle an integer overflow exception from INT64_MIN / -1.
if (lir->canBeNegativeOverflow()) {
@ -397,8 +401,12 @@ CodeGeneratorMIPS64::visitUDivOrModI64(LUDivOrModI64* lir)
Label done;
// Prevent divide by zero.
if (lir->canBeDivideByZero())
masm.ma_b(rhs, rhs, oldTrap(lir, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
if (lir->canBeDivideByZero()) {
Label nonZero;
masm.ma_b(rhs, rhs, &nonZero, Assembler::NonZero);
masm.wasmTrap(wasm::Trap::IntegerDivideByZero, lir->bytecodeOffset());
masm.bind(&nonZero);
}
masm.as_ddivu(lhs, rhs);

View File

@ -285,7 +285,10 @@ CodeGeneratorX64::visitDivOrModI64(LDivOrModI64* lir)
// Handle divide by zero.
if (lir->canBeDivideByZero()) {
masm.branchTestPtr(Assembler::Zero, rhs, rhs, oldTrap(lir, wasm::Trap::IntegerDivideByZero));
Label nonZero;
masm.branchTestPtr(Assembler::NonZero, rhs, rhs, &nonZero);
masm.wasmTrap(wasm::Trap::IntegerDivideByZero, lir->bytecodeOffset());
masm.bind(&nonZero);
}
// Handle an integer overflow exception from INT64_MIN / -1.
@ -327,8 +330,12 @@ CodeGeneratorX64::visitUDivOrModI64(LUDivOrModI64* lir)
Label done;
// Prevent divide by zero.
if (lir->canBeDivideByZero())
masm.branchTestPtr(Assembler::Zero, rhs, rhs, oldTrap(lir, wasm::Trap::IntegerDivideByZero));
if (lir->canBeDivideByZero()) {
Label nonZero;
masm.branchTestPtr(Assembler::NonZero, rhs, rhs, &nonZero);
masm.wasmTrap(wasm::Trap::IntegerDivideByZero, lir->bytecodeOffset());
masm.bind(&nonZero);
}
// Zero extend the lhs into rdx to make (rdx:rax).
masm.xorl(rdx, rdx);

View File

@ -1026,7 +1026,10 @@ CodeGeneratorX86Shared::visitUDivOrMod(LUDivOrMod* ins)
masm.test32(rhs, rhs);
if (ins->mir()->isTruncated()) {
if (ins->trapOnError()) {
masm.j(Assembler::Zero, oldTrap(ins, wasm::Trap::IntegerDivideByZero));
Label nonZero;
masm.j(Assembler::NonZero, &nonZero);
masm.wasmTrap(wasm::Trap::IntegerDivideByZero, ins->bytecodeOffset());
masm.bind(&nonZero);
} else {
ool = new(alloc()) ReturnZero(output);
masm.j(Assembler::Zero, ool->entry());
@ -1074,7 +1077,7 @@ CodeGeneratorX86Shared::visitUDivOrModConstant(LUDivOrModConstant *ins) {
if (d == 0) {
if (ins->mir()->isTruncated()) {
if (ins->trapOnError())
masm.jump(oldTrap(ins, wasm::Trap::IntegerDivideByZero));
masm.wasmTrap(wasm::Trap::IntegerDivideByZero, ins->bytecodeOffset());
else
masm.xorl(output, output);
} else {
@ -1336,7 +1339,10 @@ CodeGeneratorX86Shared::visitDivI(LDivI* ins)
if (mir->canBeDivideByZero()) {
masm.test32(rhs, rhs);
if (mir->trapOnError()) {
masm.j(Assembler::Zero, oldTrap(mir, wasm::Trap::IntegerDivideByZero));
Label nonZero;
masm.j(Assembler::NonZero, &nonZero);
masm.wasmTrap(wasm::Trap::IntegerDivideByZero, mir->bytecodeOffset());
masm.bind(&nonZero);
} else if (mir->canTruncateInfinities()) {
// Truncated division by zero is zero (Infinity|0 == 0)
if (!ool)
@ -1506,7 +1512,10 @@ CodeGeneratorX86Shared::visitModI(LModI* ins)
masm.test32(rhs, rhs);
if (mir->isTruncated()) {
if (mir->trapOnError()) {
masm.j(Assembler::Zero, oldTrap(mir, wasm::Trap::IntegerDivideByZero));
Label nonZero;
masm.j(Assembler::NonZero, &nonZero);
masm.wasmTrap(wasm::Trap::IntegerDivideByZero, mir->bytecodeOffset());
masm.bind(&nonZero);
} else {
if (!ool)
ool = new(alloc()) ReturnZero(edx);

View File

@ -1038,8 +1038,12 @@ CodeGeneratorX86::visitDivOrModI64(LDivOrModI64* lir)
Label done;
// Handle divide by zero.
if (lir->canBeDivideByZero())
masm.branchTest64(Assembler::Zero, rhs, rhs, temp, oldTrap(lir, wasm::Trap::IntegerDivideByZero));
if (lir->canBeDivideByZero()) {
Label nonZero;
masm.branchTest64(Assembler::NonZero, rhs, rhs, temp, &nonZero);
masm.wasmTrap(wasm::Trap::IntegerDivideByZero, lir->bytecodeOffset());
masm.bind(&nonZero);
}
MDefinition* mir = lir->mir();
@ -1086,8 +1090,12 @@ CodeGeneratorX86::visitUDivOrModI64(LUDivOrModI64* lir)
MOZ_ASSERT(output == ReturnReg64);
// Prevent divide by zero.
if (lir->canBeDivideByZero())
masm.branchTest64(Assembler::Zero, rhs, rhs, temp, oldTrap(lir, wasm::Trap::IntegerDivideByZero));
if (lir->canBeDivideByZero()) {
Label nonZero;
masm.branchTest64(Assembler::NonZero, rhs, rhs, temp, &nonZero);
masm.wasmTrap(wasm::Trap::IntegerDivideByZero, lir->bytecodeOffset());
masm.bind(&nonZero);
}
masm.setupWasmABICall();
masm.passABIArg(lhs.high);

View File

@ -970,7 +970,7 @@ void
MacroAssembler::branchTest64(Condition cond, Register64 lhs, Register64 rhs, Register temp,
L label)
{
if (cond == Assembler::Zero) {
if (cond == Assembler::Zero || cond == Assembler::NonZero) {
MOZ_ASSERT(lhs.low == rhs.low);
MOZ_ASSERT(lhs.high == rhs.high);
movl(lhs.low, temp);

View File

@ -3440,12 +3440,18 @@ class BaseCompiler final : public BaseCompilerInterface
}
void checkDivideByZeroI32(RegI32 rhs, RegI32 srcDest, Label* done) {
masm.branchTest32(Assembler::Zero, rhs, rhs, oldTrap(Trap::IntegerDivideByZero));
Label nonZero;
masm.branchTest32(Assembler::NonZero, rhs, rhs, &nonZero);
trap(Trap::IntegerDivideByZero);
masm.bind(&nonZero);
}
void checkDivideByZeroI64(RegI64 r) {
Label nonZero;
ScratchI32 scratch(*this);
masm.branchTest64(Assembler::Zero, r, r, scratch, oldTrap(Trap::IntegerDivideByZero));
masm.branchTest64(Assembler::NonZero, r, r, scratch, &nonZero);
trap(Trap::IntegerDivideByZero);
masm.bind(&nonZero);
}
void checkDivideSignedOverflowI32(RegI32 rhs, RegI32 srcDest, Label* done, bool zeroOnOverflow) {

View File

@ -1727,11 +1727,11 @@ wasm::GenerateStubs(const ModuleEnvironment& env, const FuncImportVector& import
switch (trap) {
case Trap::Unreachable:
case Trap::IntegerOverflow:
case Trap::IntegerDivideByZero:
case Trap::StackOverflow:
break;
// The TODO list of "old" traps to convert to new traps:
case Trap::InvalidConversionToInteger:
case Trap::IntegerDivideByZero:
case Trap::OutOfBounds:
case Trap::UnalignedAccess:
case Trap::IndirectCallToNull: