Bug 915495 - Support float32 optimization in typed array SetElem ICs. (r=bbouvier)
☠☠ backed out by e66d28e87ce1 ☠ ☠
authorShu-yu Guo <shu@rfrn.org>
Fri, 13 Sep 2013 22:45:42 -0700
changeset 160123 4229377061715d21073aa2c2bd747b77f2295537
parent 160122 853f3f44cb3bb8ff7290a266c5290272695982f2
child 160124 e66d28e87ce13c962040b5cc75304dc56c97ce9b
push id2961
push userlsblakk@mozilla.com
push dateMon, 28 Oct 2013 21:59:28 +0000
treeherdermozilla-beta@73ef4f13486f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbouvier
bugs915495
milestone26.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 915495 - Support float32 optimization in typed array SetElem ICs. (r=bbouvier)
js/src/jit-test/tests/ion/setelem-float32-typedarray-ic.js
js/src/jit/CodeGenerator.cpp
js/src/jit/CodeGenerator.h
js/src/jit/IonCaches.cpp
js/src/jit/IonMacroAssembler.cpp
js/src/jit/IonMacroAssembler.h
js/src/jit/MIR.h
js/src/jit/arm/CodeGenerator-arm.cpp
js/src/jit/arm/CodeGenerator-arm.h
js/src/jit/arm/LIR-arm.h
js/src/jit/arm/LOpcodes-arm.h
js/src/jit/arm/Lowering-arm.cpp
js/src/jit/arm/MacroAssembler-arm.h
js/src/jit/shared/Assembler-x86-shared.h
js/src/jit/shared/MacroAssembler-x86-shared.h
js/src/jit/x64/CodeGenerator-x64.cpp
js/src/jit/x64/LIR-x64.h
js/src/jit/x64/LOpcodes-x64.h
js/src/jit/x64/Lowering-x64.cpp
js/src/jit/x86/CodeGenerator-x86.cpp
js/src/jit/x86/CodeGenerator-x86.h
js/src/jit/x86/LIR-x86.h
js/src/jit/x86/LOpcodes-x86.h
js/src/jit/x86/Lowering-x86.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/setelem-float32-typedarray-ic.js
@@ -0,0 +1,11 @@
+function testFloat32SetElemIC(a) {
+  for (var i = 0; i < a.length; i++) {
+    var r = Math.fround(Math.random());
+    a[i] = r;
+    assertEq(a[i], r);
+  }
+}
+
+testFloat32SetElemIC(new Array(2048));
+testFloat32SetElemIC(new Float64Array(2048));
+testFloat32SetElemIC(new Float32Array(2048));
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -15,16 +15,17 @@
 #include "jsmath.h"
 #include "jsnum.h"
 
 #include "builtin/Eval.h"
 #include "gc/Nursery.h"
 #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"
 #include "jit/ParallelSafetyAnalysis.h"
 #include "jit/PerfSpewer.h"
 #include "vm/ForkJoin.h"
 
 #include "jsboolinlines.h"
@@ -5749,65 +5750,68 @@ CodeGenerator::link()
         break;
       default:
         MOZ_ASSUME_UNREACHABLE("No such execution mode");
     }
 
     return true;
 }
 
-// An out-of-line path to convert a boxed int32 to a double.
-class OutOfLineUnboxDouble : public OutOfLineCodeBase<CodeGenerator>
-{
-    LUnboxDouble *unboxDouble_;
+// An out-of-line path to convert a boxed int32 to either a double or float.
+class OutOfLineUnboxFloatingPoint : public OutOfLineCodeBase<CodeGenerator>
+{
+    LUnboxFloatingPoint *unboxFloatingPoint_;
 
   public:
-    OutOfLineUnboxDouble(LUnboxDouble *unboxDouble)
-      : unboxDouble_(unboxDouble)
+    OutOfLineUnboxFloatingPoint(LUnboxFloatingPoint *unboxFloatingPoint)
+      : unboxFloatingPoint_(unboxFloatingPoint)
     { }
 
     bool accept(CodeGenerator *codegen) {
-        return codegen->visitOutOfLineUnboxDouble(this);
-    }
-
-    LUnboxDouble *unboxDouble() const {
-        return unboxDouble_;
+        return codegen->visitOutOfLineUnboxFloatingPoint(this);
+    }
+
+    LUnboxFloatingPoint *unboxFloatingPoint() const {
+        return unboxFloatingPoint_;
     }
 };
 
 bool
-CodeGenerator::visitUnboxDouble(LUnboxDouble *lir)
-{
-    const ValueOperand box = ToValue(lir, LUnboxDouble::Input);
+CodeGenerator::visitUnboxFloatingPoint(LUnboxFloatingPoint *lir)
+{
+    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)
-{
-    LUnboxDouble *ins = ool->unboxDouble();
-    const ValueOperand value = ToValue(ins, LUnboxDouble::Input);
+CodeGenerator::visitOutOfLineUnboxFloatingPoint(OutOfLineUnboxFloatingPoint *ool)
+{
+    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;
 }
 
 typedef bool (*GetPropertyFn)(JSContext *, HandleValue, HandlePropertyName, MutableHandleValue);
 static const VMFunction GetPropertyInfo = FunctionInfo<GetPropertyFn>(GetProperty);
 
 bool
@@ -6695,17 +6699,19 @@ CodeGenerator::visitLoadTypedArrayElemen
     masm.bind(&done);
     return true;
 }
 
 template <typename T>
 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())
             masm.storeToTypedIntArray(arrayType, Imm32(ToInt32(value)), dest);
         else
             masm.storeToTypedIntArray(arrayType, ToRegister(value), dest);
     }
 }
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -25,17 +25,17 @@ namespace jit {
 class OutOfLineNewParallelArray;
 class OutOfLineTestObject;
 class OutOfLineNewArray;
 class OutOfLineNewObject;
 class CheckOverRecursedFailure;
 class CheckOverRecursedFailurePar;
 class OutOfLineCheckInterruptPar;
 class OutOfLineInterruptCheckImplicit;
-class OutOfLineUnboxDouble;
+class OutOfLineUnboxFloatingPoint;
 class OutOfLineStoreElementHole;
 class OutOfLineTypeOfV;
 class OutOfLineLoadTypedArray;
 class OutOfLineNewGCThingPar;
 class OutOfLineUpdateCache;
 class OutOfLineCallPostWriteBarrier;
 
 class CodeGenerator : public CodeGeneratorSpecific
@@ -267,18 +267,18 @@ class CodeGenerator : public CodeGenerat
     bool visitCheckOverRecursedFailurePar(CheckOverRecursedFailurePar *ool);
 
     bool visitCheckInterruptPar(LCheckInterruptPar *lir);
     bool visitOutOfLineCheckInterruptPar(OutOfLineCheckInterruptPar *ool);
 
     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);
     bool visitOutOfLineAbortPar(OutOfLineAbortPar *ool);
     bool visitOutOfLinePropagateAbortPar(OutOfLinePropagateAbortPar *ool);
     void loadJSScriptForBlock(MBasicBlock *block, Register reg);
     void loadOutermostJSScript(Register reg);
 
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -3397,19 +3397,21 @@ GenerateSetTypedArrayElement(JSContext *
     Register elements = temp;
     masm.loadPtr(Address(object, TypedArrayObject::dataOffset()), elements);
 
     // Set the value.
     int arrayType = tarr->type();
     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);
     } else {
         // On x86 we only have 6 registers available to use, so reuse the object
         // register to compute the intermediate value to store and restore it
         // afterwards.
         masm.push(object);
--- a/js/src/jit/IonMacroAssembler.cpp
+++ b/js/src/jit/IonMacroAssembler.cpp
@@ -300,17 +300,18 @@ MacroAssembler::moveNurseryPtr(const Imm
     if (ptr.value && gc::IsInsideNursery(GetIonContext()->cx->runtime(), (void *)ptr.value))
         embedsNurseryPointers_ = true;
 #endif
     movePtr(ptr, reg);
 }
 
 template<typename S, typename T>
 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()) {
             masm.storeFloat(value, dest);
         } else {
 #ifdef JS_MORE_DETERMINISTIC
             // See the comment in ToDoubleForTypedArray.
             masm.canonicalizeDouble(value);
@@ -326,20 +327,26 @@ StoreToTypedFloatArray(MacroAssembler &m
 #endif
         masm.storeDouble(value, dest);
         break;
       default:
         MOZ_ASSUME_UNREACHABLE("Invalid typed array type");
     }
 }
 
-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);
 }
 
 template<typename T>
 void
 MacroAssembler::loadFromTypedArray(int arrayType, const T &src, AnyRegister dest, Register temp,
                                    Label *fail)
 {
@@ -499,16 +506,20 @@ MacroAssembler::clampDoubleToUint8(Float
         ma_mov(Imm32(0xff), output, NoSetCond, Above);
         ma_b(&outOfRange, Above);
         // convert it back to see if we got the same value back
         as_vcvt(ScratchFloatReg, VFPRegister(ScratchFloatReg).uintOverlay());
         // do the check
         as_vcmp(ScratchFloatReg, input);
         as_vmrs(pc);
         ma_bic(Imm32(1), output, NoSetCond, Zero);
+        // We added 0.5 in place, but the input register might be used again,
+        // so undo it.
+        ma_vimm(0.5, ScratchFloatReg);
+        ma_vsub(input, ScratchFloatReg, input);
         bind(&outOfRange);
     }
 #else
 
     Label positive, done;
 
     // <= 0 or NaN --> 0
     zeroDouble(ScratchFloatReg);
@@ -541,16 +552,20 @@ MacroAssembler::clampDoubleToUint8(Float
 
     // > 255 --> 255
     bind(&outOfRange);
     {
         move32(Imm32(255), output);
     }
 
     bind(&done);
+
+    // The input register might be used again, so subtract the 0.5 we added.
+    loadStaticDouble(&DoubleHalf, ScratchFloatReg);
+    subDouble(ScratchFloatReg, input);
 #endif
 }
 
 void
 MacroAssembler::newGCThing(const Register &result, gc::AllocKind allocKind, Label *fail)
 {
     // Inlined equivalent of js::gc::NewGCThing() without failure case handling.
 
@@ -1369,84 +1384,91 @@ MacroAssembler::convertInt32ValueToDoubl
     branchTestInt32(Assembler::NotEqual, address, done);
     unboxInt32(address, scratch);
     convertInt32ToDouble(scratch, ScratchFloatReg);
     storeDouble(ScratchFloatReg, address);
 }
 
 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);
 
     Label isDouble, isInt32, isBool, isNull, done;
 
     branchTestDouble(Assembler::Equal, tag, &isDouble);
     branchTestInt32(Assembler::Equal, tag, &isInt32);
     branchTestBoolean(Assembler::Equal, tag, &isBool);
     branchTestNull(Assembler::Equal, tag, &isNull);
     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;
         if (v.isNumber())
             d = v.toNumber();
         else if (!StringToNumber(cx, v.toString(), &d))
             return false;
 
         if (d == js_NaN)
-            loadStaticDouble(&js_NaN, output);
+            loadStaticFloatingPoint(&js_NaN, &FloatNaN, output, outputType);
         else
-            loadConstantDouble(d, output);
+            loadConstantFloatingPoint(d, static_cast<float>(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;
     }
 
     JS_ASSERT(v.isObject());
     jump(fail);
     return true;
 }
 
@@ -1485,53 +1507,69 @@ MacroAssembler::popRooted(VMFunction::Ro
         break;
       case VMFunction::RootValue:
         Pop(valueReg);
         break;
     }
 }
 
 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");
     }
 }
 
 void
 MacroAssembler::convertDoubleToInt(FloatRegister src, Register output, Label *truncateFail,
@@ -1717,16 +1755,18 @@ MacroAssembler::convertTypedOrValueToInt
       case MIRType_Undefined:
       case MIRType_Null:
         move32(Imm32(0), output);
         break;
       case MIRType_Boolean:
       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);
         break;
       case MIRType_String:
       case MIRType_Object:
         jump(fail);
         break;
--- a/js/src/jit/IonMacroAssembler.h
+++ b/js/src/jit/IonMacroAssembler.h
@@ -280,22 +280,26 @@ class MacroAssembler : public MacroAssem
             if (holeCheck)
                 branchTestMagic(Assembler::Equal, src, hole);
             loadUnboxedValue(src, dest.type(), dest.typedReg());
         }
     }
 
     template <typename T>
     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 <typename T>
     void storeConstantOrRegister(ConstantOrRegister src, const T &dest) {
         if (src.constant())
             storeValue(src.value(), dest);
         else
             storeTypedOrValue(src.reg(), dest);
@@ -422,22 +426,26 @@ class MacroAssembler : public MacroAssem
                 Push(ImmGCPtr(str));
             }
         } else {
             Push(ImmWord(JSID_BITS(id)));
         }
     }
 
     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) {
         if (v.constant())
             Push(v.value());
         else
             Push(v.reg());
     }
@@ -990,22 +998,83 @@ class MacroAssembler : public MacroAssem
     void printf(const char *output, Register value);
 
 #if JS_TRACE_LOGGING
     void tracelogStart(JSScript *script);
     void tracelogStop();
     void tracelogLog(TraceLogging::Type type);
 #endif
 
+#define FLOATING_POINT_OP_2(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)
+    {
+        FLOATING_POINT_OP_2(loadStatic, destType, dp, fp, dest);
+    }
+    void loadConstantFloatingPoint(double d, float f, FloatRegister dest, MIRType destType) {
+        FLOATING_POINT_OP_2(loadConstant, destType, d, f, dest);
+    }
+    void boolValueToFloatingPoint(ValueOperand value, FloatRegister dest, MIRType destType) {
+        FLOATING_POINT_OP_2(boolValueTo, destType, value, value, dest);
+    }
+    void int32ValueToFloatingPoint(ValueOperand value, FloatRegister dest, MIRType destType) {
+        FLOATING_POINT_OP_2(int32ValueTo, destType, value, value, dest);
+    }
+    void convertInt32ToFloatingPoint(Register src, FloatRegister dest, MIRType destType) {
+        FLOATING_POINT_OP_2(convertInt32To, destType, src, src, dest);
+    }
+
+#undef FLOATING_POINT_OP_2
+
+    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,
         IntConversion_NegativeZeroCheck,
         IntConversion_Truncate,
         IntConversion_ClampToUint8,
     };
 
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -6959,16 +6959,18 @@ class MSetElementCache
 
     bool strict() const {
         return strict_;
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
+
+    bool canConsumeFloat32() const { return true; }
 };
 
 class MCallGetProperty
   : public MUnaryInstruction,
     public BoxInputsPolicy
 {
     CompilerRootPropertyName name_;
     bool idempotent_;
--- a/js/src/jit/arm/CodeGenerator-arm.cpp
+++ b/js/src/jit/arm/CodeGenerator-arm.cpp
@@ -1259,25 +1259,29 @@ CodeGeneratorARM::visitBox(LBox *box)
     // On x86, the input operand and the output payload have the same
     // virtual register. All that needs to be written is the type tag for
     // the type definition.
     masm.ma_mov(Imm32(MIRTypeToTag(box->type())), ToRegister(type));
     return true;
 }
 
 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, reg);
+
     //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;
 }
 
 bool
 CodeGeneratorARM::visitUnbox(LUnbox *unbox)
 {
     // Note that for unbox, the type and payload indexes are switched on the
     // inputs.
--- a/js/src/jit/arm/CodeGenerator-arm.h
+++ b/js/src/jit/arm/CodeGenerator-arm.h
@@ -125,17 +125,17 @@ class CodeGeneratorARM : public CodeGene
     bool modICommon(MMod *mir, Register lhs, Register rhs, Register output, LSnapshot *snapshot,
                     Label &done);
 
   public:
     CodeGeneratorARM(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm);
 
   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);
     bool visitDouble(LDouble *ins);
 
     bool visitLoadSlotV(LLoadSlotV *load);
     bool visitLoadSlotT(LLoadSlotT *load);
     bool visitStoreSlotT(LStoreSlotT *load);
--- a/js/src/jit/arm/LIR-arm.h
+++ b/js/src/jit/arm/LIR-arm.h
@@ -23,25 +23,33 @@ class LBox : public LInstructionHelper<2
         setOperand(0, in_payload);
     }
 
     MIRType type() const {
         return type_;
     }
 };
 
-class LBoxDouble : public LInstructionHelper<2, 1, 1>
+class LBoxFloatingPoint : public LInstructionHelper<2, 1, 1>
 {
+    MIRType type_;
+
   public:
-    LIR_HEADER(BoxDouble);
+    LIR_HEADER(BoxFloatingPoint);
 
-    LBoxDouble(const LAllocation &in, const LDefinition &temp) {
+    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>
 {
   public:
     LIR_HEADER(Unbox);
 
     MUnbox *mir() const {
@@ -50,26 +58,36 @@ class LUnbox : public LInstructionHelper
     const LAllocation *payload() {
         return getOperand(0);
     }
     const LAllocation *type() {
         return getOperand(1);
     }
 };
 
-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.
 class LUInt32ToDouble : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(UInt32ToDouble)
 
--- a/js/src/jit/arm/LOpcodes-arm.h
+++ b/js/src/jit/arm/LOpcodes-arm.h
@@ -4,19 +4,19 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef jit_arm_LOpcodes_arm_h
 #define jit_arm_LOpcodes_arm_h
 
 #define LIR_CPU_OPCODE_LIST(_)  \
     _(Unbox)                    \
-    _(UnboxDouble)              \
+    _(UnboxFloatingPoint)       \
     _(Box)                      \
-    _(BoxDouble)                \
+    _(BoxFloatingPoint)         \
     _(DivI)                     \
     _(SoftDivI)                 \
     _(DivPowTwoI)               \
     _(ModI)                     \
     _(SoftModI)                 \
     _(ModPowTwoI)               \
     _(ModMaskI)                 \
     _(PowHalfD)                 \
--- a/js/src/jit/arm/Lowering-arm.cpp
+++ b/js/src/jit/arm/Lowering-arm.cpp
@@ -77,18 +77,19 @@ LIRGeneratorARM::visitConstant(MConstant
 }
 
 bool
 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);
 
     if (inner->isConstant())
         return defineBox(new LValue(inner->toConstant()->value()), box);
 
     LBox *lir = new LBox(use(inner), inner->type());
@@ -118,21 +119,21 @@ LIRGeneratorARM::visitUnbox(MUnbox *unbo
     // An unbox on arm reads in a type tag (either in memory or a register) and
     // a payload. Unlike most instructions conusming a box, we ask for the type
     // second, so that the result can re-use the first input.
     MDefinition *inner = unbox->getOperand(0);
 
     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);
     }
 
     // Swap the order we use the box pieces so we can re-use the payload register.
     LUnbox *lir = new LUnbox;
     lir->setOperand(0, usePayloadInRegisterAtStart(inner));
     lir->setOperand(1, useType(inner, LUse::REGISTER));
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -1452,16 +1452,19 @@ class MacroAssemblerARMCompat : public M
         return as_cmp(bounded, Imm8(0));
     }
 
     void storeFloat(VFPRegister src, Register base, Register index, Condition cond) {
         as_vcvt(VFPRegister(ScratchFloatReg).singleOverlay(), src, false, cond);
         ma_vstr(VFPRegister(ScratchFloatReg).singleOverlay(), base, index, 0, cond);
 
     }
+    void moveFloat(FloatRegister src, FloatRegister dest) {
+        ma_vmov(VFPRegister(src).singleOverlay(), VFPRegister(dest).singleOverlay());
+    }
 };
 
 typedef MacroAssemblerARMCompat MacroAssemblerSpecific;
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_arm_MacroAssembler_arm_h */
--- a/js/src/jit/shared/Assembler-x86-shared.h
+++ b/js/src/jit/shared/Assembler-x86-shared.h
@@ -324,16 +324,20 @@ class AssemblerX86Shared
             break;
           case Operand::MEM_SCALE:
             masm.movsd_rm(src.code(), dest.disp(), dest.base(), dest.index(), dest.scale());
             break;
           default:
             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()) {
           case Operand::FPREG:
             masm.movss_rr(src.fpu(), dest.code());
             break;
           case Operand::MEM_REG_DISP:
             masm.movss_mr(src.disp(), src.base(), dest.code());
--- a/js/src/jit/shared/MacroAssembler-x86-shared.h
+++ b/js/src/jit/shared/MacroAssembler-x86-shared.h
@@ -387,16 +387,19 @@ class MacroAssemblerX86Shared : public A
         movss(src, dest);
     }
     void storeFloat(FloatRegister src, const Address &dest) {
         movss(src, Operand(dest));
     }
     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
     // the given snapshot. This function overwrites the scratch float register.
     void convertDoubleToInt32(FloatRegister src, Register dest, Label *fail,
                               bool negativeZeroCheck = true)
     {
         cvttsd2si(src, dest);
--- a/js/src/jit/x64/CodeGenerator-x64.cpp
+++ b/js/src/jit/x64/CodeGenerator-x64.cpp
@@ -79,20 +79,23 @@ CodeGeneratorX64::visitOsrValue(LOsrValu
 }
 
 bool
 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())) {
+        if (box->type() == MIRType_Float32)
+            masm.convertFloatToDouble(ToFloatRegister(in), ToFloatRegister(in));
+        masm.movq(ToFloatRegister(in), ToRegister(result));
+    } else {
         masm.boxValue(ValueTypeFromMIRType(box->type()), ToRegister(in), ToRegister(result));
-    else
-        masm.movq(ToFloatRegister(in), ToRegister(result));
+    }
     return true;
 }
 
 bool
 CodeGeneratorX64::visitUnbox(LUnbox *unbox)
 {
     const ValueOperand value = ToValue(unbox, LUnbox::Input);
     const LDefinition *result = unbox->output();
--- a/js/src/jit/x64/LIR-x64.h
+++ b/js/src/jit/x64/LIR-x64.h
@@ -49,23 +49,30 @@ class LUnbox : public LUnboxBase {
   public:
     LIR_HEADER(Unbox)
 
     LUnbox(const LAllocation &input)
       : LUnboxBase(input)
     { }
 };
 
-class LUnboxDouble : public LUnboxBase {
+class LUnboxFloatingPoint : public LUnboxBase {
+    MIRType type_;
+
   public:
-    LIR_HEADER(UnboxDouble)
+    LIR_HEADER(UnboxFloatingPoint)
 
-    LUnboxDouble(const LAllocation &input)
-      : LUnboxBase(input)
+    LUnboxFloatingPoint(const LAllocation &input, MIRType type)
+      : LUnboxBase(input),
+        type_(type)
     { }
+
+    MIRType type() const {
+        return type_;
+    }
 };
 
 // Convert a 32-bit unsigned integer to a double.
 class LUInt32ToDouble : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(UInt32ToDouble)
 
--- a/js/src/jit/x64/LOpcodes-x64.h
+++ b/js/src/jit/x64/LOpcodes-x64.h
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef jit_x64_LOpcodes_x64_h
 #define jit_x64_LOpcodes_x64_h
 
 #define LIR_CPU_OPCODE_LIST(_)      \
     _(Box)                          \
     _(Unbox)                        \
-    _(UnboxDouble)                  \
+    _(UnboxFloatingPoint)           \
     _(DivI)                         \
     _(DivPowTwoI)                   \
     _(DivSelfI)                     \
     _(ModI)                         \
     _(ModPowTwoI)                   \
     _(PowHalfD)                     \
     _(UInt32ToDouble)               \
     _(AsmJSLoadFuncPtr)             \
--- a/js/src/jit/x64/Lowering-x64.cpp
+++ b/js/src/jit/x64/Lowering-x64.cpp
@@ -71,18 +71,18 @@ LIRGeneratorX64::visitBox(MBox *box)
     return define(ins, box, LDefinition(LDefinition::BOX));
 }
 
 bool
 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));
 
     if (unbox->fallible() && !assignSnapshot(lir, unbox->bailoutKind()))
         return false;
 
     return define(lir, unbox);
 }
--- a/js/src/jit/x86/CodeGenerator-x86.cpp
+++ b/js/src/jit/x86/CodeGenerator-x86.cpp
@@ -113,22 +113,25 @@ CodeGeneratorX86::visitBox(LBox *box)
     // On x86, the input operand and the output payload have the same
     // virtual register. All that needs to be written is the type tag for
     // the type definition.
     masm.movl(Imm32(MIRTypeToTag(box->type())), ToRegister(type));
     return true;
 }
 
 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, reg);
+    masm.boxDouble(reg, out);
     return true;
 }
 
 bool
 CodeGeneratorX86::visitUnbox(LUnbox *unbox)
 {
     // Note that for unbox, the type and payload indexes are switched on the
     // inputs.
--- a/js/src/jit/x86/CodeGenerator-x86.h
+++ b/js/src/jit/x86/CodeGenerator-x86.h
@@ -43,17 +43,17 @@ class CodeGeneratorX86 : public CodeGene
     void storeElementTyped(const LAllocation *value, MIRType valueType, MIRType elementType,
                            const Register &elements, const LAllocation *index);
 
   public:
     CodeGeneratorX86(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm);
 
   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);
     bool visitLoadSlotV(LLoadSlotV *load);
     bool visitLoadSlotT(LLoadSlotT *load);
     bool visitStoreSlotT(LStoreSlotT *store);
     bool visitLoadElementT(LLoadElementT *load);
     bool visitImplicitThis(LImplicitThis *lir);
--- a/js/src/jit/x86/LIR-x86.h
+++ b/js/src/jit/x86/LIR-x86.h
@@ -23,25 +23,34 @@ class LBox : public LInstructionHelper<2
         setOperand(0, in_payload);
     }
 
     MIRType type() const {
         return type_;
     }
 };
 
-class LBoxDouble : public LInstructionHelper<2, 1, 1>
+class LBoxFloatingPoint : public LInstructionHelper<2, 1, 1>
 {
+    MIRType type_;
+
   public:
-    LIR_HEADER(BoxDouble);
+    LIR_HEADER(BoxFloatingPoint);
 
-    LBoxDouble(const LAllocation &in, const LDefinition &temp) {
+    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>
 {
   public:
     LIR_HEADER(Unbox);
 
     MUnbox *mir() const {
@@ -50,26 +59,36 @@ class LUnbox : public LInstructionHelper
     const LAllocation *payload() {
         return getOperand(0);
     }
     const LAllocation *type() {
         return getOperand(1);
     }
 };
 
-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.
 class LUInt32ToDouble : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(UInt32ToDouble)
 
--- a/js/src/jit/x86/LOpcodes-x86.h
+++ b/js/src/jit/x86/LOpcodes-x86.h
@@ -4,19 +4,19 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef jit_x86_LOpcodes_x86_h
 #define jit_x86_LOpcodes_x86_h
 
 #define LIR_CPU_OPCODE_LIST(_)  \
     _(Unbox)                    \
-    _(UnboxDouble)              \
+    _(UnboxFloatingPoint)       \
     _(Box)                      \
-    _(BoxDouble)                \
+    _(BoxFloatingPoint)         \
     _(DivI)                     \
     _(DivPowTwoI)               \
     _(DivSelfI)                 \
     _(ModI)                     \
     _(ModPowTwoI)               \
     _(PowHalfD)                 \
     _(UInt32ToDouble)           \
     _(AsmJSLoadFuncPtr)         \
--- a/js/src/jit/x86/Lowering-x86.cpp
+++ b/js/src/jit/x86/Lowering-x86.cpp
@@ -54,18 +54,19 @@ LIRGeneratorX86::useByteOpRegisterOrNonD
 }
 
 bool
 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);
 
     if (inner->isConstant())
         return defineBox(new LValue(inner->toConstant()->value()), box);
 
     LBox *lir = new LBox(use(inner), inner->type());
@@ -95,21 +96,21 @@ LIRGeneratorX86::visitUnbox(MUnbox *unbo
     // An unbox on x86 reads in a type tag (either in memory or a register) and
     // a payload. Unlike most instructions conusming a box, we ask for the type
     // second, so that the result can re-use the first input.
     MDefinition *inner = unbox->getOperand(0);
 
     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);
     }
 
     // Swap the order we use the box pieces so we can re-use the payload register.
     LUnbox *lir = new LUnbox;
     lir->setOperand(0, usePayloadInRegisterAtStart(inner));
     lir->setOperand(1, useType(inner, LUse::ANY));