From 9af7246a474bb824f39562b68e5f7fae0921a8d9 Mon Sep 17 00:00:00 2001 From: Lars T Hansen Date: Mon, 6 Jun 2016 15:11:51 +0200 Subject: [PATCH] Bug 1232205 - Wasm baseline: Factor outOfLineWasmTruncateCheck and outOfLineTruncateSlow, on x86-shared. r=bbouvier --HG-- extra : rebase_source : 06266204a20175e6939be925869c1cdcb5159d74 --- js/src/jit/MacroAssembler.cpp | 43 +++++++++++++ js/src/jit/MacroAssembler.h | 3 + js/src/jit/shared/CodeGenerator-shared.cpp | 41 ++---------- .../x86-shared/CodeGenerator-x86-shared.cpp | 58 +---------------- .../x86-shared/MacroAssembler-x86-shared.cpp | 64 +++++++++++++++++++ .../x86-shared/MacroAssembler-x86-shared.h | 3 + 6 files changed, 121 insertions(+), 91 deletions(-) diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp index 93b58b602115..4883b89bdb15 100644 --- a/js/src/jit/MacroAssembler.cpp +++ b/js/src/jit/MacroAssembler.cpp @@ -1819,6 +1819,49 @@ MacroAssembler::convertTypedOrValueToFloatingPoint(TypedOrValueRegister src, Flo } } +void +MacroAssembler::outOfLineTruncateSlow(FloatRegister src, Register dest, bool widenFloatToDouble, + bool compilingWasm) +{ +#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) + if (widenFloatToDouble) { + convertFloat32ToDouble(src, ScratchDoubleReg); + src = ScratchDoubleReg; + } +#elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64) + FloatRegister srcSingle; + if (widenFloatToDouble) { + MOZ_ASSERT(src.isSingle()); + srcSingle = src; + src = src.asDouble(); + push(srcSingle); + convertFloat32ToDouble(srcSingle, src); + } +#else + // Also see below + MOZ_CRASH("MacroAssembler platform hook: outOfLineTruncateSlow"); +#endif + + MOZ_ASSERT(src.isDouble()); + + setupUnalignedABICall(dest); + passABIArg(src, MoveOp::DOUBLE); + if (compilingWasm) + callWithABI(wasm::SymbolicAddress::ToInt32); + else + callWithABI(mozilla::BitwiseCast(JS::ToInt32)); + storeCallResult(dest); + +#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) + // Nothing +#elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64) + if (widenFloatToDouble) + pop(srcSingle); +#else + MOZ_CRASH("MacroAssembler platform hook: outOfLineTruncateSlow"); +#endif +} + void MacroAssembler::convertDoubleToInt(FloatRegister src, Register output, FloatRegister temp, Label* truncateFail, Label* fail, diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h index bd8127f3afff..a8fa17cc5e5e 100644 --- a/js/src/jit/MacroAssembler.h +++ b/js/src/jit/MacroAssembler.h @@ -1642,6 +1642,9 @@ class MacroAssembler : public MacroAssemblerSpecific void convertTypedOrValueToFloatingPoint(TypedOrValueRegister src, FloatRegister output, Label* fail, MIRType outputType); + void outOfLineTruncateSlow(FloatRegister src, Register dest, bool widenFloatToDouble, + bool compilingAsmJS); + void convertInt32ValueToDouble(const Address& address, Register scratch, Label* done); void convertValueToDouble(ValueOperand value, FloatRegister output, Label* fail) { convertValueToFloatingPoint(value, output, fail, MIRType::Double); diff --git a/js/src/jit/shared/CodeGenerator-shared.cpp b/js/src/jit/shared/CodeGenerator-shared.cpp index 7d22e56c3e05..2dd0c556d112 100644 --- a/js/src/jit/shared/CodeGenerator-shared.cpp +++ b/js/src/jit/shared/CodeGenerator-shared.cpp @@ -1398,11 +1398,11 @@ class OutOfLineTruncateSlow : public OutOfLineCodeBase { FloatRegister src_; Register dest_; - bool needFloat32Conversion_; + bool widenFloatToDouble_; public: - OutOfLineTruncateSlow(FloatRegister src, Register dest, bool needFloat32Conversion = false) - : src_(src), dest_(dest), needFloat32Conversion_(needFloat32Conversion) + OutOfLineTruncateSlow(FloatRegister src, Register dest, bool widenFloatToDouble = false) + : src_(src), dest_(dest), widenFloatToDouble_(widenFloatToDouble) { } void accept(CodeGeneratorShared* codegen) { @@ -1414,8 +1414,8 @@ class OutOfLineTruncateSlow : public OutOfLineCodeBase Register dest() const { return dest_; } - bool needFloat32Conversion() const { - return needFloat32Conversion_; + bool widenFloatToDouble() const { + return widenFloatToDouble_; } }; @@ -1454,36 +1454,9 @@ CodeGeneratorShared::visitOutOfLineTruncateSlow(OutOfLineTruncateSlow* ool) Register dest = ool->dest(); saveVolatile(dest); - -#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) - if (ool->needFloat32Conversion()) { - masm.convertFloat32ToDouble(src, ScratchDoubleReg); - src = ScratchDoubleReg; - } -#else - FloatRegister srcSingle = src.asSingle(); - if (ool->needFloat32Conversion()) { - MOZ_ASSERT(src.isSingle()); - masm.push(src); - masm.convertFloat32ToDouble(src, src); - src = src.asDouble(); - } -#endif - - masm.setupUnalignedABICall(dest); - masm.passABIArg(src, MoveOp::DOUBLE); - if (gen->compilingAsmJS()) - masm.callWithABI(wasm::SymbolicAddress::ToInt32); - else - masm.callWithABI(BitwiseCast(JS::ToInt32)); - masm.storeCallResult(dest); - -#if !defined(JS_CODEGEN_ARM) && !defined(JS_CODEGEN_ARM64) - if (ool->needFloat32Conversion()) - masm.pop(srcSingle); -#endif - + masm.outOfLineTruncateSlow(src, dest, ool->widenFloatToDouble(), gen->compilingAsmJS()); restoreVolatile(dest); + masm.jump(ool->rejoin()); } diff --git a/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp b/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp index 0edd7a1f5618..ce50be4ac046 100644 --- a/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp +++ b/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp @@ -4475,63 +4475,7 @@ CodeGeneratorX86Shared::visitOutOfLineWasmTruncateCheck(OutOfLineWasmTruncateChe MIRType fromType = ool->fromType(); MIRType toType = ool->toType(); - // Eagerly take care of NaNs. - Label inputIsNaN; - if (fromType == MIRType::Double) - masm.branchDouble(Assembler::DoubleUnordered, input, input, &inputIsNaN); - else if (fromType == MIRType::Float32) - masm.branchFloat(Assembler::DoubleUnordered, input, input, &inputIsNaN); - else - MOZ_CRASH("unexpected type in visitOutOfLineWasmTruncateCheck"); - - Label fail; - - // Handle special values (not needed for unsigned values). - if (!ool->isUnsigned()) { - if (toType == MIRType::Int32) { - // MWasmTruncateToInt32 - if (fromType == MIRType::Double) { - // We've used vcvttsd2si. The only valid double values that can - // truncate to INT32_MIN are in ]INT32_MIN - 1; INT32_MIN]. - masm.loadConstantDouble(double(INT32_MIN) - 1.0, ScratchDoubleReg); - masm.branchDouble(Assembler::DoubleLessThanOrEqual, input, ScratchDoubleReg, &fail); - - masm.loadConstantDouble(double(INT32_MIN), ScratchDoubleReg); - masm.branchDouble(Assembler::DoubleGreaterThan, input, ScratchDoubleReg, &fail); - } else { - MOZ_ASSERT(fromType == MIRType::Float32); - - // We've used vcvttss2si. Check that the input wasn't - // float(INT32_MIN), which is the only legimitate input that - // would truncate to INT32_MIN. - masm.loadConstantFloat32(float(INT32_MIN), ScratchFloat32Reg); - masm.branchFloat(Assembler::DoubleNotEqual, input, ScratchFloat32Reg, &fail); - } - } else { - // MWasmTruncateToInt64 - MOZ_ASSERT(toType == MIRType::Int64); - if (fromType == MIRType::Double) { - // We've used vcvtsd2sq. The only legit value whose i64 - // truncation is INT64_MIN is double(INT64_MIN): exponent is so - // high that the highest resolution around is much more than 1. - masm.loadConstantDouble(double(int64_t(INT64_MIN)), ScratchDoubleReg); - masm.branchDouble(Assembler::DoubleNotEqual, input, ScratchDoubleReg, &fail); - } else { - // We've used vcvtss2sq. Same comment applies. - MOZ_ASSERT(fromType == MIRType::Float32); - masm.loadConstantFloat32(float(int64_t(INT64_MIN)), ScratchFloat32Reg); - masm.branchFloat(Assembler::DoubleNotEqual, input, ScratchFloat32Reg, &fail); - } - } - masm.jump(ool->rejoin()); - } - - // Handle errors. - masm.bind(&fail); - masm.jump(wasm::JumpTarget::IntegerOverflow); - - masm.bind(&inputIsNaN); - masm.jump(wasm::JumpTarget::InvalidConversionToInteger); + masm.outOfLineWasmTruncateCheck(input, fromType, toType, ool->isUnsigned(), ool->rejoin()); } void diff --git a/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp b/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp index 62ccdd7f4a44..e97ac8c86a10 100644 --- a/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp +++ b/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp @@ -403,6 +403,70 @@ MacroAssemblerX86Shared::minMaxFloat32(FloatRegister first, FloatRegister second bind(&done); } +void +MacroAssemblerX86Shared::outOfLineWasmTruncateCheck(FloatRegister input, MIRType fromType, + MIRType toType, bool isUnsigned, + Label* rejoin) +{ + // Eagerly take care of NaNs. + Label inputIsNaN; + if (fromType == MIRType::Double) + asMasm().branchDouble(Assembler::DoubleUnordered, input, input, &inputIsNaN); + else if (fromType == MIRType::Float32) + asMasm().branchFloat(Assembler::DoubleUnordered, input, input, &inputIsNaN); + else + MOZ_CRASH("unexpected type in visitOutOfLineWasmTruncateCheck"); + + Label fail; + + // Handle special values (not needed for unsigned values). + if (!isUnsigned) { + if (toType == MIRType::Int32) { + // MWasmTruncateToInt32 + if (fromType == MIRType::Double) { + // We've used vcvttsd2si. The only valid double values that can + // truncate to INT32_MIN are in ]INT32_MIN - 1; INT32_MIN]. + asMasm().loadConstantDouble(double(INT32_MIN) - 1.0, ScratchDoubleReg); + asMasm().branchDouble(Assembler::DoubleLessThanOrEqual, input, ScratchDoubleReg, &fail); + + asMasm().loadConstantDouble(double(INT32_MIN), ScratchDoubleReg); + asMasm().branchDouble(Assembler::DoubleGreaterThan, input, ScratchDoubleReg, &fail); + } else { + MOZ_ASSERT(fromType == MIRType::Float32); + + // We've used vcvttss2si. Check that the input wasn't + // float(INT32_MIN), which is the only legimitate input that + // would truncate to INT32_MIN. + asMasm().loadConstantFloat32(float(INT32_MIN), ScratchFloat32Reg); + asMasm().branchFloat(Assembler::DoubleNotEqual, input, ScratchFloat32Reg, &fail); + } + } else { + // MWasmTruncateToInt64 + MOZ_ASSERT(toType == MIRType::Int64); + if (fromType == MIRType::Double) { + // We've used vcvtsd2sq. The only legit value whose i64 + // truncation is INT64_MIN is double(INT64_MIN): exponent is so + // high that the highest resolution around is much more than 1. + asMasm().loadConstantDouble(double(int64_t(INT64_MIN)), ScratchDoubleReg); + asMasm().branchDouble(Assembler::DoubleNotEqual, input, ScratchDoubleReg, &fail); + } else { + // We've used vcvtss2sq. Same comment applies. + MOZ_ASSERT(fromType == MIRType::Float32); + asMasm().loadConstantFloat32(float(int64_t(INT64_MIN)), ScratchFloat32Reg); + asMasm().branchFloat(Assembler::DoubleNotEqual, input, ScratchFloat32Reg, &fail); + } + } + jump(rejoin); + } + + // Handle errors. + bind(&fail); + jump(wasm::JumpTarget::IntegerOverflow); + + bind(&inputIsNaN); + jump(wasm::JumpTarget::InvalidConversionToInteger); +} + //{{{ check_macroassembler_style // =============================================================== // MacroAssembler high-level usage. diff --git a/js/src/jit/x86-shared/MacroAssembler-x86-shared.h b/js/src/jit/x86-shared/MacroAssembler-x86-shared.h index aee5861c95f4..18597f7893b3 100644 --- a/js/src/jit/x86-shared/MacroAssembler-x86-shared.h +++ b/js/src/jit/x86-shared/MacroAssembler-x86-shared.h @@ -107,6 +107,9 @@ class MacroAssemblerX86Shared : public Assembler void minMaxDouble(FloatRegister first, FloatRegister second, bool handleNaN, bool isMax); void minMaxFloat32(FloatRegister first, FloatRegister second, bool handleNaN, bool isMax); + void outOfLineWasmTruncateCheck(FloatRegister input, MIRType fromType, MIRType toType, + bool isUnsigned, Label* rejoin); + void compareDouble(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs) { if (cond & DoubleConditionBitInvert) vucomisd(lhs, rhs);