diff --git a/js/src/jit-test/tests/ion/setelem-float32-typedarray-ic.js b/js/src/jit-test/tests/ion/setelem-float32-typedarray-ic.js new file mode 100644 index 000000000000..6ad44f4dcec8 --- /dev/null +++ b/js/src/jit-test/tests/ion/setelem-float32-typedarray-ic.js @@ -0,0 +1,23 @@ +function testFloat32SetElemIC(a) { + for (var i = 0; i < a.length; i++) { + var r = Math.fround(Math.random()); + a[i] = r; + assertEq(a[i], r); + } +} + +function testCompoundClamping(a, b) { + for (var i = 0; i < a.length; i++) { + var r = Math.random(); + a[i] = b[i] = r; + assertEq(a[i], b[i]); + } +} + +testFloat32SetElemIC(new Array(2048)); +testFloat32SetElemIC(new Float64Array(2048)); +testFloat32SetElemIC(new Float32Array(2048)); + +testCompoundClamping(new Array(2048), new Array(2048)); +testCompoundClamping(new Uint8Array(2048), new Uint8Array(2048)); +testCompoundClamping(new Uint8ClampedArray(2048), new Uint8ClampedArray(2048)); diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index 47924554f16e..e9145efa5905 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -20,6 +20,7 @@ #include "jit/ExecutionModeInlines.h" #include "jit/IonLinker.h" #include "jit/IonSpewer.h" +#include "jit/Lowering.h" #include "jit/MIRGenerator.h" #include "jit/MoveEmitter.h" #include "jit/ParallelFunctions.h" @@ -5754,55 +5755,58 @@ CodeGenerator::link() return true; } -// An out-of-line path to convert a boxed int32 to a double. -class OutOfLineUnboxDouble : public OutOfLineCodeBase +// An out-of-line path to convert a boxed int32 to either a float or double. +class OutOfLineUnboxFloatingPoint : public OutOfLineCodeBase { - LUnboxDouble *unboxDouble_; + LUnboxFloatingPoint *unboxFloatingPoint_; public: - OutOfLineUnboxDouble(LUnboxDouble *unboxDouble) - : unboxDouble_(unboxDouble) + OutOfLineUnboxFloatingPoint(LUnboxFloatingPoint *unboxFloatingPoint) + : unboxFloatingPoint_(unboxFloatingPoint) { } bool accept(CodeGenerator *codegen) { - return codegen->visitOutOfLineUnboxDouble(this); + return codegen->visitOutOfLineUnboxFloatingPoint(this); } - LUnboxDouble *unboxDouble() const { - return unboxDouble_; + LUnboxFloatingPoint *unboxFloatingPoint() const { + return unboxFloatingPoint_; } }; bool -CodeGenerator::visitUnboxDouble(LUnboxDouble *lir) +CodeGenerator::visitUnboxFloatingPoint(LUnboxFloatingPoint *lir) { - const ValueOperand box = ToValue(lir, LUnboxDouble::Input); + const ValueOperand box = ToValue(lir, LUnboxFloatingPoint::Input); const LDefinition *result = lir->output(); // Out-of-line path to convert int32 to double or bailout // if this instruction is fallible. - OutOfLineUnboxDouble *ool = new OutOfLineUnboxDouble(lir); + OutOfLineUnboxFloatingPoint *ool = new OutOfLineUnboxFloatingPoint(lir); if (!addOutOfLineCode(ool)) return false; + FloatRegister resultReg = ToFloatRegister(result); masm.branchTestDouble(Assembler::NotEqual, box, ool->entry()); - masm.unboxDouble(box, ToFloatRegister(result)); + masm.unboxDouble(box, resultReg); + if (lir->type() == MIRType_Float32) + masm.convertDoubleToFloat(resultReg, resultReg); masm.bind(ool->rejoin()); return true; } bool -CodeGenerator::visitOutOfLineUnboxDouble(OutOfLineUnboxDouble *ool) +CodeGenerator::visitOutOfLineUnboxFloatingPoint(OutOfLineUnboxFloatingPoint *ool) { - LUnboxDouble *ins = ool->unboxDouble(); - const ValueOperand value = ToValue(ins, LUnboxDouble::Input); + LUnboxFloatingPoint *ins = ool->unboxFloatingPoint(); + const ValueOperand value = ToValue(ins, LUnboxFloatingPoint::Input); if (ins->mir()->fallible()) { Assembler::Condition cond = masm.testInt32(Assembler::NotEqual, value); if (!bailoutIf(cond, ins->snapshot())) return false; } - masm.int32ValueToDouble(value, ToFloatRegister(ins->output())); + masm.int32ValueToFloatingPoint(value, ToFloatRegister(ins->output()), ins->type()); masm.jump(ool->rejoin()); return true; } @@ -6700,7 +6704,9 @@ template static inline void StoreToTypedArray(MacroAssembler &masm, int arrayType, const LAllocation *value, const T &dest) { - if (arrayType == ScalarTypeRepresentation::TYPE_FLOAT32 || arrayType == ScalarTypeRepresentation::TYPE_FLOAT64) { + if (arrayType == ScalarTypeRepresentation::TYPE_FLOAT32 || + arrayType == ScalarTypeRepresentation::TYPE_FLOAT64) + { masm.storeToTypedFloatArray(arrayType, ToFloatRegister(value), dest); } else { if (value->isConstant()) diff --git a/js/src/jit/CodeGenerator.h b/js/src/jit/CodeGenerator.h index 3bd375f13478..a520b485a67d 100644 --- a/js/src/jit/CodeGenerator.h +++ b/js/src/jit/CodeGenerator.h @@ -30,7 +30,7 @@ class CheckOverRecursedFailure; class CheckOverRecursedFailurePar; class OutOfLineCheckInterruptPar; class OutOfLineInterruptCheckImplicit; -class OutOfLineUnboxDouble; +class OutOfLineUnboxFloatingPoint; class OutOfLineStoreElementHole; class OutOfLineTypeOfV; class OutOfLineLoadTypedArray; @@ -272,8 +272,8 @@ class CodeGenerator : public CodeGeneratorSpecific bool visitInterruptCheckImplicit(LInterruptCheckImplicit *ins); bool visitOutOfLineInterruptCheckImplicit(OutOfLineInterruptCheckImplicit *ins); - bool visitUnboxDouble(LUnboxDouble *lir); - bool visitOutOfLineUnboxDouble(OutOfLineUnboxDouble *ool); + bool visitUnboxFloatingPoint(LUnboxFloatingPoint *lir); + bool visitOutOfLineUnboxFloatingPoint(OutOfLineUnboxFloatingPoint *ool); bool visitOutOfLineStoreElementHole(OutOfLineStoreElementHole *ool); bool visitOutOfLineNewGCThingPar(OutOfLineNewGCThingPar *ool); diff --git a/js/src/jit/IonCaches.cpp b/js/src/jit/IonCaches.cpp index 455d9ab872f0..1dfb60798428 100644 --- a/js/src/jit/IonCaches.cpp +++ b/js/src/jit/IonCaches.cpp @@ -3402,9 +3402,11 @@ GenerateSetTypedArrayElement(JSContext *cx, MacroAssembler &masm, IonCache::Stub int width = TypedArrayObject::slotWidth(arrayType); BaseIndex target(elements, index, ScaleFromElemWidth(width)); - if (arrayType == ScalarTypeRepresentation::TYPE_FLOAT32 || - arrayType == ScalarTypeRepresentation::TYPE_FLOAT64) - { + if (arrayType == ScalarTypeRepresentation::TYPE_FLOAT32) { + if (!masm.convertConstantOrRegisterToFloat(cx, value, tempFloat, &failures)) + return false; + masm.storeToTypedFloatArray(arrayType, tempFloat, target); + } else if (arrayType == ScalarTypeRepresentation::TYPE_FLOAT64) { if (!masm.convertConstantOrRegisterToDouble(cx, value, tempFloat, &failures)) return false; masm.storeToTypedFloatArray(arrayType, tempFloat, target); diff --git a/js/src/jit/IonMacroAssembler.cpp b/js/src/jit/IonMacroAssembler.cpp index 58dce74daadf..e86bb8f89d62 100644 --- a/js/src/jit/IonMacroAssembler.cpp +++ b/js/src/jit/IonMacroAssembler.cpp @@ -305,7 +305,8 @@ MacroAssembler::moveNurseryPtr(const ImmMaybeNurseryPtr &ptr, const Register &re template static void -StoreToTypedFloatArray(MacroAssembler &masm, int arrayType, const S &value, const T &dest) { +StoreToTypedFloatArray(MacroAssembler &masm, int arrayType, const S &value, const T &dest) +{ switch (arrayType) { case ScalarTypeRepresentation::TYPE_FLOAT32: if (LIRGenerator::allowFloat32Optimizations()) { @@ -331,10 +332,16 @@ StoreToTypedFloatArray(MacroAssembler &masm, int arrayType, const S &value, cons } } -void MacroAssembler::storeToTypedFloatArray(int arrayType, const FloatRegister &value, const BaseIndex &dest) { +void +MacroAssembler::storeToTypedFloatArray(int arrayType, const FloatRegister &value, + const BaseIndex &dest) +{ StoreToTypedFloatArray(*this, arrayType, value, dest); } -void MacroAssembler::storeToTypedFloatArray(int arrayType, const FloatRegister &value, const Address &dest) { +void +MacroAssembler::storeToTypedFloatArray(int arrayType, const FloatRegister &value, + const Address &dest) +{ StoreToTypedFloatArray(*this, arrayType, value, dest); } @@ -1374,9 +1381,13 @@ MacroAssembler::convertInt32ValueToDouble(const Address &address, Register scrat static const double DoubleZero = 0.0; static const double DoubleOne = 1.0; +static const float FloatZero = 0.0; +static const float FloatOne = 1.0; +static const float FloatNaN = js_NaN; void -MacroAssembler::convertValueToDouble(ValueOperand value, FloatRegister output, Label *fail) +MacroAssembler::convertValueToFloatingPoint(ValueOperand value, FloatRegister output, + Label *fail, MIRType outputType) { Register tag = splitTagForTest(value); @@ -1389,28 +1400,31 @@ MacroAssembler::convertValueToDouble(ValueOperand value, FloatRegister output, L branchTestUndefined(Assembler::NotEqual, tag, fail); // fall-through: undefined - loadStaticDouble(&js_NaN, output); + loadStaticFloatingPoint(&js_NaN, &FloatNaN, output, outputType); jump(&done); bind(&isNull); - loadStaticDouble(&DoubleZero, output); + loadStaticFloatingPoint(&DoubleZero, &FloatZero, output, outputType); jump(&done); bind(&isBool); - boolValueToDouble(value, output); + boolValueToFloatingPoint(value, output, outputType); jump(&done); bind(&isInt32); - int32ValueToDouble(value, output); + int32ValueToFloatingPoint(value, output, outputType); jump(&done); bind(&isDouble); unboxDouble(value, output); + if (outputType == MIRType_Float32) + convertDoubleToFloat(output, output); bind(&done); } bool -MacroAssembler::convertValueToDouble(JSContext *cx, const Value &v, FloatRegister output, Label *fail) +MacroAssembler::convertValueToFloatingPoint(JSContext *cx, const Value &v, FloatRegister output, + Label *fail, MIRType outputType) { if (v.isNumber() || v.isString()) { double d; @@ -1420,28 +1434,28 @@ MacroAssembler::convertValueToDouble(JSContext *cx, const Value &v, FloatRegiste return false; if (d == js_NaN) - loadStaticDouble(&js_NaN, output); + loadStaticFloatingPoint(&js_NaN, &FloatNaN, output, outputType); else - loadConstantDouble(d, output); + loadConstantFloatingPoint(d, static_cast(d), output, outputType); return true; } if (v.isBoolean()) { if (v.toBoolean()) - loadStaticDouble(&DoubleOne, output); + loadStaticFloatingPoint(&DoubleOne, &FloatOne, output, outputType); else - loadStaticDouble(&DoubleZero, output); + loadStaticFloatingPoint(&DoubleZero, &FloatZero, output, outputType); return true; } if (v.isNull()) { - loadStaticDouble(&DoubleZero, output); + loadStaticFloatingPoint(&DoubleZero, &FloatZero, output, outputType); return true; } if (v.isUndefined()) { - loadStaticDouble(&js_NaN, output); + loadStaticFloatingPoint(&js_NaN, &FloatNaN, output, outputType); return true; } @@ -1490,43 +1504,59 @@ MacroAssembler::popRooted(VMFunction::RootType rootType, Register cellReg, } bool -MacroAssembler::convertConstantOrRegisterToDouble(JSContext *cx, ConstantOrRegister src, - FloatRegister output, Label *fail) +MacroAssembler::convertConstantOrRegisterToFloatingPoint(JSContext *cx, ConstantOrRegister src, + FloatRegister output, Label *fail, + MIRType outputType) { if (src.constant()) - return convertValueToDouble(cx, src.value(), output, fail); + return convertValueToFloatingPoint(cx, src.value(), output, fail, outputType); - convertTypedOrValueToDouble(src.reg(), output, fail); + convertTypedOrValueToFloatingPoint(src.reg(), output, fail, outputType); return true; } void -MacroAssembler::convertTypedOrValueToDouble(TypedOrValueRegister src, FloatRegister output, - Label *fail) +MacroAssembler::convertTypedOrValueToFloatingPoint(TypedOrValueRegister src, FloatRegister output, + Label *fail, MIRType outputType) { + JS_ASSERT(IsFloatingPointType(outputType)); + if (src.hasValue()) { - convertValueToDouble(src.valueReg(), output, fail); + convertValueToFloatingPoint(src.valueReg(), output, fail, outputType); return; } + bool outputIsDouble = outputType == MIRType_Double; switch (src.type()) { case MIRType_Null: - loadStaticDouble(&DoubleZero, output); + loadStaticFloatingPoint(&DoubleZero, &FloatZero, output, outputType); break; case MIRType_Boolean: case MIRType_Int32: - convertInt32ToDouble(src.typedReg().gpr(), output); + convertInt32ToFloatingPoint(src.typedReg().gpr(), output, outputType); + break; + case MIRType_Float32: + if (outputIsDouble) { + convertFloatToDouble(src.typedReg().fpu(), output); + } else { + if (src.typedReg().fpu() != output) + moveFloat(src.typedReg().fpu(), output); + } break; case MIRType_Double: - if (src.typedReg().fpu() != output) - moveDouble(src.typedReg().fpu(), output); + if (outputIsDouble) { + if (src.typedReg().fpu() != output) + moveDouble(src.typedReg().fpu(), output); + } else { + convertDoubleToFloat(src.typedReg().fpu(), output); + } break; case MIRType_Object: case MIRType_String: jump(fail); break; case MIRType_Undefined: - loadStaticDouble(&js_NaN, output); + loadStaticFloatingPoint(&js_NaN, &FloatNaN, output, outputType); break; default: MOZ_ASSUME_UNREACHABLE("Bad MIRType"); @@ -1534,8 +1564,9 @@ MacroAssembler::convertTypedOrValueToDouble(TypedOrValueRegister src, FloatRegis } void -MacroAssembler::convertDoubleToInt(FloatRegister src, Register output, Label *truncateFail, - Label *fail, IntConversionBehavior behavior) +MacroAssembler::convertDoubleToInt(FloatRegister src, Register output, FloatRegister temp, + Label *truncateFail, Label *fail, + IntConversionBehavior behavior) { switch (behavior) { case IntConversion_Normal: @@ -1546,7 +1577,9 @@ MacroAssembler::convertDoubleToInt(FloatRegister src, Register output, Label *tr branchTruncateDouble(src, output, truncateFail ? truncateFail : fail); break; case IntConversion_ClampToUint8: - clampDoubleToUint8(src, output); + // Clamping clobbers the input register, so use a temp. + moveDouble(src, temp); + clampDoubleToUint8(temp, output); break; } } @@ -1613,7 +1646,7 @@ MacroAssembler::convertValueToInt(ValueOperand value, MDefinition *maybeInput, if (handleStrings) bind(handleStringRejoin); - convertDoubleToInt(temp, output, truncateDoubleSlow, fail, behavior); + convertDoubleToInt(temp, output, temp, truncateDoubleSlow, fail, behavior); jump(&done); } @@ -1722,9 +1755,11 @@ MacroAssembler::convertTypedOrValueToInt(TypedOrValueRegister src, FloatRegister case MIRType_Int32: if (src.typedReg().gpr() != output) move32(src.typedReg().gpr(), output); + if (src.type() == MIRType_Int32 && behavior == IntConversion_ClampToUint8) + clampIntToUint8(output); break; case MIRType_Double: - convertDoubleToInt(src.typedReg().fpu(), output, NULL, fail, behavior); + convertDoubleToInt(src.typedReg().fpu(), output, temp, NULL, fail, behavior); break; case MIRType_String: case MIRType_Object: diff --git a/js/src/jit/IonMacroAssembler.h b/js/src/jit/IonMacroAssembler.h index f10aa1d45fee..9d6518a86c69 100644 --- a/js/src/jit/IonMacroAssembler.h +++ b/js/src/jit/IonMacroAssembler.h @@ -285,12 +285,16 @@ class MacroAssembler : public MacroAssemblerSpecific template void storeTypedOrValue(TypedOrValueRegister src, const T &dest) { - if (src.hasValue()) + if (src.hasValue()) { storeValue(src.valueReg(), dest); - else if (src.type() == MIRType_Double) - storeDouble(src.typedReg().fpu(), dest); - else + } else if (IsFloatingPointType(src.type())) { + FloatRegister reg = src.typedReg().fpu(); + if (src.type() == MIRType_Float32) + convertFloatToDouble(reg, reg); + storeDouble(reg, dest); + } else { storeValue(ValueTypeFromMIRType(src.type()), src.typedReg().gpr(), dest); + } } template @@ -427,12 +431,16 @@ class MacroAssembler : public MacroAssemblerSpecific } void Push(TypedOrValueRegister v) { - if (v.hasValue()) + if (v.hasValue()) { Push(v.valueReg()); - else if (IsFloatingPointType(v.type())) - Push(v.typedReg().fpu()); - else + } else if (IsFloatingPointType(v.type())) { + FloatRegister reg = v.typedReg().fpu(); + if (v.type() == MIRType_Float32) + convertFloatToDouble(reg, reg); + Push(reg); + } else { Push(ValueTypeFromMIRType(v.type()), v.typedReg().gpr()); + } } void Push(ConstantOrRegister v) { @@ -995,12 +1003,73 @@ class MacroAssembler : public MacroAssemblerSpecific void tracelogLog(TraceLogging::Type type); #endif +#define DISPATCH_FLOATING_POINT_OP(method, type, arg1d, arg1f, arg2) \ + JS_ASSERT(IsFloatingPointType(type)); \ + if (type == MIRType_Double) \ + method##Double(arg1d, arg2); \ + else \ + method##Float32(arg1f, arg2); \ + + void loadStaticFloatingPoint(const double *dp, const float *fp, FloatRegister dest, + MIRType destType) + { + DISPATCH_FLOATING_POINT_OP(loadStatic, destType, dp, fp, dest); + } + void loadConstantFloatingPoint(double d, float f, FloatRegister dest, MIRType destType) { + DISPATCH_FLOATING_POINT_OP(loadConstant, destType, d, f, dest); + } + void boolValueToFloatingPoint(ValueOperand value, FloatRegister dest, MIRType destType) { + DISPATCH_FLOATING_POINT_OP(boolValueTo, destType, value, value, dest); + } + void int32ValueToFloatingPoint(ValueOperand value, FloatRegister dest, MIRType destType) { + DISPATCH_FLOATING_POINT_OP(int32ValueTo, destType, value, value, dest); + } + void convertInt32ToFloatingPoint(Register src, FloatRegister dest, MIRType destType) { + DISPATCH_FLOATING_POINT_OP(convertInt32To, destType, src, src, dest); + } + +#undef DISPATCH_FLOATING_POINT_OP + + void convertValueToFloatingPoint(ValueOperand value, FloatRegister output, Label *fail, + MIRType outputType); + bool convertValueToFloatingPoint(JSContext *cx, const Value &v, FloatRegister output, + Label *fail, MIRType outputType); + bool convertConstantOrRegisterToFloatingPoint(JSContext *cx, ConstantOrRegister src, + FloatRegister output, Label *fail, + MIRType outputType); + void convertTypedOrValueToFloatingPoint(TypedOrValueRegister src, FloatRegister output, + Label *fail, MIRType outputType); + void convertInt32ValueToDouble(const Address &address, Register scratch, Label *done); - void convertValueToDouble(ValueOperand value, FloatRegister output, Label *fail); - bool convertValueToDouble(JSContext *cx, const Value &v, FloatRegister output, Label *fail); + void convertValueToDouble(ValueOperand value, FloatRegister output, Label *fail) { + convertValueToFloatingPoint(value, output, fail, MIRType_Double); + } + bool convertValueToDouble(JSContext *cx, const Value &v, FloatRegister output, Label *fail) { + return convertValueToFloatingPoint(cx, v, output, fail, MIRType_Double); + } bool convertConstantOrRegisterToDouble(JSContext *cx, ConstantOrRegister src, - FloatRegister output, Label *fail); - void convertTypedOrValueToDouble(TypedOrValueRegister src, FloatRegister output, Label *fail); + FloatRegister output, Label *fail) + { + return convertConstantOrRegisterToFloatingPoint(cx, src, output, fail, MIRType_Double); + } + void convertTypedOrValueToDouble(TypedOrValueRegister src, FloatRegister output, Label *fail) { + convertTypedOrValueToFloatingPoint(src, output, fail, MIRType_Double); + } + + void convertValueToFloat(ValueOperand value, FloatRegister output, Label *fail) { + convertValueToFloatingPoint(value, output, fail, MIRType_Float32); + } + bool convertValueToFloat(JSContext *cx, const Value &v, FloatRegister output, Label *fail) { + return convertValueToFloatingPoint(cx, v, output, fail, MIRType_Float32); + } + bool convertConstantOrRegisterToFloat(JSContext *cx, ConstantOrRegister src, + FloatRegister output, Label *fail) + { + return convertConstantOrRegisterToFloatingPoint(cx, src, output, fail, MIRType_Float32); + } + void convertTypedOrValueToFloat(TypedOrValueRegister src, FloatRegister output, Label *fail) { + convertTypedOrValueToFloatingPoint(src, output, fail, MIRType_Float32); + } enum IntConversionBehavior { IntConversion_Normal, @@ -1012,8 +1081,8 @@ class MacroAssembler : public MacroAssemblerSpecific // // Functions for converting values to int. // - void convertDoubleToInt(FloatRegister src, Register output, Label *truncateFail, Label *fail, - IntConversionBehavior behavior); + void convertDoubleToInt(FloatRegister src, Register output, FloatRegister temp, + Label *truncateFail, Label *fail, IntConversionBehavior behavior); // Strings may be handled by providing labels to jump to when the behavior // is truncation or clamping. The subroutine, usually an OOL call, is diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index f489ce375c6d..36bf37f42f15 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -6964,6 +6964,8 @@ class MSetElementCache TypePolicy *typePolicy() { return this; } + + bool canConsumeFloat32() const { return true; } }; class MCallGetProperty diff --git a/js/src/jit/arm/CodeGenerator-arm.cpp b/js/src/jit/arm/CodeGenerator-arm.cpp index 4dac94529efe..42eec44d3c39 100644 --- a/js/src/jit/arm/CodeGenerator-arm.cpp +++ b/js/src/jit/arm/CodeGenerator-arm.cpp @@ -1264,15 +1264,21 @@ CodeGeneratorARM::visitBox(LBox *box) } bool -CodeGeneratorARM::visitBoxDouble(LBoxDouble *box) +CodeGeneratorARM::visitBoxFloatingPoint(LBoxFloatingPoint *box) { const LDefinition *payload = box->getDef(PAYLOAD_INDEX); const LDefinition *type = box->getDef(TYPE_INDEX); const LAllocation *in = box->getOperand(0); + FloatRegister reg = ToFloatRegister(in); + if (box->type() == MIRType_Float32) { + masm.convertFloatToDouble(reg, ScratchFloatReg); + reg = ScratchFloatReg; + } + //masm.as_vxfer(ToRegister(payload), ToRegister(type), // VFPRegister(ToFloatRegister(in)), Assembler::FloatToCore); - masm.ma_vxfer(VFPRegister(ToFloatRegister(in)), ToRegister(payload), ToRegister(type)); + masm.ma_vxfer(VFPRegister(reg), ToRegister(payload), ToRegister(type)); return true; } diff --git a/js/src/jit/arm/CodeGenerator-arm.h b/js/src/jit/arm/CodeGenerator-arm.h index f54e6bd1f246..9327c1c4c8c8 100644 --- a/js/src/jit/arm/CodeGenerator-arm.h +++ b/js/src/jit/arm/CodeGenerator-arm.h @@ -130,7 +130,7 @@ class CodeGeneratorARM : public CodeGeneratorShared public: bool visitBox(LBox *box); - bool visitBoxDouble(LBoxDouble *box); + bool visitBoxFloatingPoint(LBoxFloatingPoint *box); bool visitUnbox(LUnbox *unbox); bool visitValue(LValue *value); bool visitOsrValue(LOsrValue *value); diff --git a/js/src/jit/arm/LIR-arm.h b/js/src/jit/arm/LIR-arm.h index 381f7dceb42d..cc3c5129da69 100644 --- a/js/src/jit/arm/LIR-arm.h +++ b/js/src/jit/arm/LIR-arm.h @@ -28,15 +28,23 @@ class LBox : public LInstructionHelper<2, 1, 0> } }; -class LBoxDouble : public LInstructionHelper<2, 1, 1> +class LBoxFloatingPoint : public LInstructionHelper<2, 1, 1> { - public: - LIR_HEADER(BoxDouble); + MIRType type_; - LBoxDouble(const LAllocation &in, const LDefinition &temp) { + public: + LIR_HEADER(BoxFloatingPoint); + + LBoxFloatingPoint(const LAllocation &in, const LDefinition &temp, MIRType type) + : type_(type) + { setOperand(0, in); setTemp(0, temp); } + + MIRType type() const { + return type_; + } }; class LUnbox : public LInstructionHelper<1, 2, 0> @@ -55,16 +63,26 @@ class LUnbox : public LInstructionHelper<1, 2, 0> } }; -class LUnboxDouble : public LInstructionHelper<1, 2, 0> +class LUnboxFloatingPoint : public LInstructionHelper<1, 2, 0> { + MIRType type_; + public: - LIR_HEADER(UnboxDouble); + LIR_HEADER(UnboxFloatingPoint); static const size_t Input = 0; + LUnboxFloatingPoint(MIRType type) + : type_(type) + { } + MUnbox *mir() const { return mir_->toUnbox(); } + + MIRType type() const { + return type_; + } }; // Convert a 32-bit unsigned integer to a double. diff --git a/js/src/jit/arm/LOpcodes-arm.h b/js/src/jit/arm/LOpcodes-arm.h index 932794ea99aa..de4654d31e03 100644 --- a/js/src/jit/arm/LOpcodes-arm.h +++ b/js/src/jit/arm/LOpcodes-arm.h @@ -9,9 +9,9 @@ #define LIR_CPU_OPCODE_LIST(_) \ _(Unbox) \ - _(UnboxDouble) \ + _(UnboxFloatingPoint) \ _(Box) \ - _(BoxDouble) \ + _(BoxFloatingPoint) \ _(DivI) \ _(SoftDivI) \ _(DivPowTwoI) \ diff --git a/js/src/jit/arm/Lowering-arm.cpp b/js/src/jit/arm/Lowering-arm.cpp index cd6e4ce862ea..61d8c0ed2eee 100644 --- a/js/src/jit/arm/Lowering-arm.cpp +++ b/js/src/jit/arm/Lowering-arm.cpp @@ -82,8 +82,9 @@ LIRGeneratorARM::visitBox(MBox *box) MDefinition *inner = box->getOperand(0); // If the box wrapped a double, it needs a new register. - if (inner->type() == MIRType_Double) - return defineBox(new LBoxDouble(useRegisterAtStart(inner), tempCopy(inner, 0)), box); + if (IsFloatingPointType(inner->type())) + return defineBox(new LBoxFloatingPoint(useRegisterAtStart(inner), tempCopy(inner, 0), + inner->type()), box); if (box->canEmitAtUses()) return emitAtUses(box); @@ -123,11 +124,11 @@ LIRGeneratorARM::visitUnbox(MUnbox *unbox) if (!ensureDefined(inner)) return false; - if (unbox->type() == MIRType_Double) { - LUnboxDouble *lir = new LUnboxDouble(); + if (IsFloatingPointType(unbox->type())) { + LUnboxFloatingPoint *lir = new LUnboxFloatingPoint(unbox->type()); if (unbox->fallible() && !assignSnapshot(lir, unbox->bailoutKind())) return false; - if (!useBox(lir, LUnboxDouble::Input, inner)) + if (!useBox(lir, LUnboxFloatingPoint::Input, inner)) return false; return define(lir, unbox); } diff --git a/js/src/jit/arm/MacroAssembler-arm.h b/js/src/jit/arm/MacroAssembler-arm.h index fc3e455c149b..5215ada8e207 100644 --- a/js/src/jit/arm/MacroAssembler-arm.h +++ b/js/src/jit/arm/MacroAssembler-arm.h @@ -784,6 +784,9 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM void loadStaticFloat32(const float *dp, const FloatRegister &dest) { MOZ_ASSUME_UNREACHABLE("NYI"); } + void loadConstantFloat32(const float dp, const FloatRegister &dest) { + MOZ_ASSUME_UNREACHABLE("NYI"); + } template void branchTestInt32(Condition cond, const T & t, Label *label) { @@ -1457,6 +1460,9 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM ma_vstr(VFPRegister(ScratchFloatReg).singleOverlay(), base, index, 0, cond); } + void moveFloat(FloatRegister src, FloatRegister dest) { + as_vmov(VFPRegister(src).singleOverlay(), VFPRegister(dest).singleOverlay()); + } }; typedef MacroAssemblerARMCompat MacroAssemblerSpecific; diff --git a/js/src/jit/shared/Assembler-x86-shared.h b/js/src/jit/shared/Assembler-x86-shared.h index 2850b43246f9..59a6ecc3063f 100644 --- a/js/src/jit/shared/Assembler-x86-shared.h +++ b/js/src/jit/shared/Assembler-x86-shared.h @@ -329,6 +329,10 @@ class AssemblerX86Shared MOZ_ASSUME_UNREACHABLE("unexpected operand kind"); } } + void movss(const FloatRegister &src, const FloatRegister &dest) { + JS_ASSERT(HasSSE2()); + masm.movss_rr(src.code(), dest.code()); + } void movss(const Operand &src, const FloatRegister &dest) { JS_ASSERT(HasSSE2()); switch (src.kind()) { diff --git a/js/src/jit/shared/MacroAssembler-x86-shared.h b/js/src/jit/shared/MacroAssembler-x86-shared.h index 2abff48ccc9d..ef71040e3bb2 100644 --- a/js/src/jit/shared/MacroAssembler-x86-shared.h +++ b/js/src/jit/shared/MacroAssembler-x86-shared.h @@ -392,6 +392,9 @@ class MacroAssemblerX86Shared : public Assembler void storeFloat(FloatRegister src, const BaseIndex &dest) { movss(src, Operand(dest)); } + void moveFloat(FloatRegister src, FloatRegister dest) { + movss(src, dest); + } // Checks whether a double is representable as a 32-bit integer. If so, the // integer is written to the output register. Otherwise, a bailout is taken to diff --git a/js/src/jit/x64/CodeGenerator-x64.cpp b/js/src/jit/x64/CodeGenerator-x64.cpp index e7053241ddad..e886fc77f456 100644 --- a/js/src/jit/x64/CodeGenerator-x64.cpp +++ b/js/src/jit/x64/CodeGenerator-x64.cpp @@ -84,10 +84,16 @@ CodeGeneratorX64::visitBox(LBox *box) const LAllocation *in = box->getOperand(0); const LDefinition *result = box->getDef(0); - if (box->type() != MIRType_Double) + if (IsFloatingPointType(box->type())) { + FloatRegister reg = ToFloatRegister(in); + if (box->type() == MIRType_Float32) { + masm.convertFloatToDouble(reg, ScratchFloatReg); + reg = ScratchFloatReg; + } + masm.movq(reg, ToRegister(result)); + } else { masm.boxValue(ValueTypeFromMIRType(box->type()), ToRegister(in), ToRegister(result)); - else - masm.movq(ToFloatRegister(in), ToRegister(result)); + } return true; } diff --git a/js/src/jit/x64/LIR-x64.h b/js/src/jit/x64/LIR-x64.h index bf12728b41ca..0ef53062e44a 100644 --- a/js/src/jit/x64/LIR-x64.h +++ b/js/src/jit/x64/LIR-x64.h @@ -54,13 +54,20 @@ class LUnbox : public LUnboxBase { { } }; -class LUnboxDouble : public LUnboxBase { - public: - LIR_HEADER(UnboxDouble) +class LUnboxFloatingPoint : public LUnboxBase { + MIRType type_; - LUnboxDouble(const LAllocation &input) - : LUnboxBase(input) + public: + LIR_HEADER(UnboxFloatingPoint) + + LUnboxFloatingPoint(const LAllocation &input, MIRType type) + : LUnboxBase(input), + type_(type) { } + + MIRType type() const { + return type_; + } }; // Convert a 32-bit unsigned integer to a double. diff --git a/js/src/jit/x64/LOpcodes-x64.h b/js/src/jit/x64/LOpcodes-x64.h index 72d600541856..a37ebe6d5dd7 100644 --- a/js/src/jit/x64/LOpcodes-x64.h +++ b/js/src/jit/x64/LOpcodes-x64.h @@ -10,7 +10,7 @@ #define LIR_CPU_OPCODE_LIST(_) \ _(Box) \ _(Unbox) \ - _(UnboxDouble) \ + _(UnboxFloatingPoint) \ _(DivI) \ _(DivPowTwoI) \ _(DivSelfI) \ diff --git a/js/src/jit/x64/Lowering-x64.cpp b/js/src/jit/x64/Lowering-x64.cpp index eb41eacd57a3..4ae8ff92f653 100644 --- a/js/src/jit/x64/Lowering-x64.cpp +++ b/js/src/jit/x64/Lowering-x64.cpp @@ -76,8 +76,8 @@ LIRGeneratorX64::visitUnbox(MUnbox *unbox) { MDefinition *box = unbox->getOperand(0); LUnboxBase *lir; - if (unbox->type() == MIRType_Double) - lir = new LUnboxDouble(useRegister(box)); + if (IsFloatingPointType(unbox->type())) + lir = new LUnboxFloatingPoint(useRegister(box), unbox->type()); else lir = new LUnbox(useRegister(box)); diff --git a/js/src/jit/x86/CodeGenerator-x86.cpp b/js/src/jit/x86/CodeGenerator-x86.cpp index 0e5be3c5b565..bbd705728fc7 100644 --- a/js/src/jit/x86/CodeGenerator-x86.cpp +++ b/js/src/jit/x86/CodeGenerator-x86.cpp @@ -118,12 +118,17 @@ CodeGeneratorX86::visitBox(LBox *box) } bool -CodeGeneratorX86::visitBoxDouble(LBoxDouble *box) +CodeGeneratorX86::visitBoxFloatingPoint(LBoxFloatingPoint *box) { const LAllocation *in = box->getOperand(0); const ValueOperand out = ToOutValue(box); - masm.boxDouble(ToFloatRegister(in), out); + FloatRegister reg = ToFloatRegister(in); + if (box->type() == MIRType_Float32) { + masm.convertFloatToDouble(reg, ScratchFloatReg); + reg = ScratchFloatReg; + } + masm.boxDouble(reg, out); return true; } diff --git a/js/src/jit/x86/CodeGenerator-x86.h b/js/src/jit/x86/CodeGenerator-x86.h index 0d7afd168576..f2523a4d70ad 100644 --- a/js/src/jit/x86/CodeGenerator-x86.h +++ b/js/src/jit/x86/CodeGenerator-x86.h @@ -48,7 +48,7 @@ class CodeGeneratorX86 : public CodeGeneratorX86Shared public: bool visitBox(LBox *box); - bool visitBoxDouble(LBoxDouble *box); + bool visitBoxFloatingPoint(LBoxFloatingPoint *box); bool visitUnbox(LUnbox *unbox); bool visitValue(LValue *value); bool visitOsrValue(LOsrValue *value); diff --git a/js/src/jit/x86/LIR-x86.h b/js/src/jit/x86/LIR-x86.h index b38f80cd9b7e..1275d1acd06e 100644 --- a/js/src/jit/x86/LIR-x86.h +++ b/js/src/jit/x86/LIR-x86.h @@ -28,15 +28,24 @@ class LBox : public LInstructionHelper<2, 1, 0> } }; -class LBoxDouble : public LInstructionHelper<2, 1, 1> +class LBoxFloatingPoint : public LInstructionHelper<2, 1, 1> { - public: - LIR_HEADER(BoxDouble); + MIRType type_; - LBoxDouble(const LAllocation &in, const LDefinition &temp) { + public: + LIR_HEADER(BoxFloatingPoint); + + LBoxFloatingPoint(const LAllocation &in, const LDefinition &temp, MIRType type) + : type_(type) + { + JS_ASSERT(IsFloatingPointType(type)); setOperand(0, in); setTemp(0, temp); } + + MIRType type() const { + return type_; + } }; class LUnbox : public LInstructionHelper<1, 2, 0> @@ -55,16 +64,26 @@ class LUnbox : public LInstructionHelper<1, 2, 0> } }; -class LUnboxDouble : public LInstructionHelper<1, 2, 0> +class LUnboxFloatingPoint : public LInstructionHelper<1, 2, 0> { + MIRType type_; + public: - LIR_HEADER(UnboxDouble); + LIR_HEADER(UnboxFloatingPoint); static const size_t Input = 0; + LUnboxFloatingPoint(MIRType type) + : type_(type) + { } + MUnbox *mir() const { return mir_->toUnbox(); } + + MIRType type() const { + return type_; + } }; // Convert a 32-bit unsigned integer to a double. diff --git a/js/src/jit/x86/LOpcodes-x86.h b/js/src/jit/x86/LOpcodes-x86.h index 52123d185422..f9e13faa7eac 100644 --- a/js/src/jit/x86/LOpcodes-x86.h +++ b/js/src/jit/x86/LOpcodes-x86.h @@ -9,9 +9,9 @@ #define LIR_CPU_OPCODE_LIST(_) \ _(Unbox) \ - _(UnboxDouble) \ + _(UnboxFloatingPoint) \ _(Box) \ - _(BoxDouble) \ + _(BoxFloatingPoint) \ _(DivI) \ _(DivPowTwoI) \ _(DivSelfI) \ diff --git a/js/src/jit/x86/Lowering-x86.cpp b/js/src/jit/x86/Lowering-x86.cpp index ff9fbd9c0562..4d0caada7e33 100644 --- a/js/src/jit/x86/Lowering-x86.cpp +++ b/js/src/jit/x86/Lowering-x86.cpp @@ -59,8 +59,9 @@ LIRGeneratorX86::visitBox(MBox *box) MDefinition *inner = box->getOperand(0); // If the box wrapped a double, it needs a new register. - if (inner->type() == MIRType_Double) - return defineBox(new LBoxDouble(useRegisterAtStart(inner), tempCopy(inner, 0)), box); + if (IsFloatingPointType(inner->type())) + return defineBox(new LBoxFloatingPoint(useRegisterAtStart(inner), tempCopy(inner, 0), + inner->type()), box); if (box->canEmitAtUses()) return emitAtUses(box); @@ -100,11 +101,11 @@ LIRGeneratorX86::visitUnbox(MUnbox *unbox) if (!ensureDefined(inner)) return false; - if (unbox->type() == MIRType_Double) { - LUnboxDouble *lir = new LUnboxDouble; + if (IsFloatingPointType(unbox->type())) { + LUnboxFloatingPoint *lir = new LUnboxFloatingPoint(unbox->type()); if (unbox->fallible() && !assignSnapshot(lir, unbox->bailoutKind())) return false; - if (!useBox(lir, LUnboxDouble::Input, inner)) + if (!useBox(lir, LUnboxFloatingPoint::Input, inner)) return false; return define(lir, unbox); }