Bug 1326027: Remove RawF32 and RawF64; r=luke
authorBenjamin Bouvier <benj@benj.me>
Fri, 30 Dec 2016 10:35:47 +0100
changeset 355664 8c07ff4ab630c8a753e820c3d68db95df0c29af5
parent 355663 adb05b1d381cbc9b6c7fa251108862e21a3d25d7
child 355665 f99c8421337505979789a2aac5764ea5b2a69c0c
push id10621
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 16:02:43 +0000
treeherdermozilla-aurora@dca7b42e6c67 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1326027
milestone53.0a1
Bug 1326027: Remove RawF32 and RawF64; r=luke MozReview-Commit-ID: ArjweiIrq0j
js/src/jit/MIR.cpp
js/src/jit/MIR.h
js/src/jit/arm/Assembler-arm.cpp
js/src/jit/arm/Assembler-arm.h
js/src/jit/arm/MacroAssembler-arm.cpp
js/src/jit/arm/MacroAssembler-arm.h
js/src/jit/arm64/MacroAssembler-arm64.h
js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp
js/src/jit/mips-shared/MacroAssembler-mips-shared.h
js/src/jit/mips32/MacroAssembler-mips32.cpp
js/src/jit/mips32/MacroAssembler-mips32.h
js/src/jit/mips64/MacroAssembler-mips64.cpp
js/src/jit/mips64/MacroAssembler-mips64.h
js/src/jit/none/MacroAssembler-none.h
js/src/jit/shared/LIR-shared.h
js/src/jit/shared/Lowering-shared.cpp
js/src/jit/shared/Lowering-shared.h
js/src/jit/x64/MacroAssembler-x64.cpp
js/src/jit/x64/MacroAssembler-x64.h
js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp
js/src/jit/x86-shared/MacroAssembler-x86-shared.h
js/src/jit/x86/MacroAssembler-x86-inl.h
js/src/jit/x86/MacroAssembler-x86.cpp
js/src/jit/x86/MacroAssembler-x86.h
js/src/wasm/AsmJS.cpp
js/src/wasm/WasmBaselineCompile.cpp
js/src/wasm/WasmBinaryIterator.h
js/src/wasm/WasmBinaryToAST.cpp
js/src/wasm/WasmBinaryToExperimentalText.cpp
js/src/wasm/WasmBinaryToText.cpp
js/src/wasm/WasmIonCompile.cpp
js/src/wasm/WasmJS.cpp
js/src/wasm/WasmModule.cpp
js/src/wasm/WasmTextToBinary.cpp
js/src/wasm/WasmTextUtils.cpp
js/src/wasm/WasmTextUtils.h
js/src/wasm/WasmTypes.h
js/src/wasm/WasmValidate.cpp
js/src/wasm/WasmValidate.h
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -155,19 +155,19 @@ EvaluateConstantOperands(TempAllocator& 
       default:
         MOZ_CRASH("NYI");
     }
 
     // For a float32 or double value, use the Raw* New so that we preserve NaN
     // bits. This isn't strictly required for either ES or wasm, but it does
     // avoid making constant-folding observable.
     if (ins->type() == MIRType::Double)
-        return MConstant::New(alloc, wasm::RawF64(ret));
+        return MConstant::NewRawDouble(alloc, ret);
     if (ins->type() == MIRType::Float32)
-        return MConstant::New(alloc, wasm::RawF32(float(ret)));
+        return MConstant::NewRawFloat32(alloc, float(ret));
 
     Value retVal;
     retVal.setNumber(JS::CanonicalizeNaN(ret));
 
     // If this was an int32 operation but the result isn't an int32 (for
     // example, a division where the numerator isn't evenly divisible by the
     // denominator), decline folding.
     MOZ_ASSERT(ins->type() == MIRType::Int32);
@@ -808,39 +808,35 @@ MConstant::New(TempAllocator& alloc, con
 
 MConstant*
 MConstant::New(TempAllocator::Fallible alloc, const Value& v, CompilerConstraintList* constraints)
 {
     return new(alloc) MConstant(v, constraints);
 }
 
 MConstant*
+MConstant::NewRawFloat32(TempAllocator& alloc, float f)
+{
+    return new(alloc) MConstant(f);
+}
+
+MConstant*
+MConstant::NewRawDouble(TempAllocator& alloc, double d)
+{
+    return new(alloc) MConstant(d);
+}
+
+MConstant*
 MConstant::NewFloat32(TempAllocator& alloc, double d)
 {
     MOZ_ASSERT(IsNaN(d) || d == double(float(d)));
     return new(alloc) MConstant(float(d));
 }
 
 MConstant*
-MConstant::New(TempAllocator& alloc, wasm::RawF32 f)
-{
-    auto* c = new(alloc) MConstant(Int32Value(f.bits()), nullptr);
-    c->setResultType(MIRType::Float32);
-    return c;
-}
-
-MConstant*
-MConstant::New(TempAllocator& alloc, wasm::RawF64 d)
-{
-    auto* c = new(alloc) MConstant(int64_t(d.bits()));
-    c->setResultType(MIRType::Double);
-    return c;
-}
-
-MConstant*
 MConstant::NewInt64(TempAllocator& alloc, int64_t i)
 {
     return new(alloc) MConstant(i);
 }
 
 MConstant*
 MConstant::New(TempAllocator& alloc, const Value& v, MIRType type)
 {
@@ -3294,20 +3290,20 @@ MMinMax::foldsTo(TempAllocator& alloc)
 
         // The folded MConstant should maintain the same MIRType with
         // the original MMinMax.
         if (type() == MIRType::Int32) {
             int32_t cast;
             if (mozilla::NumberEqualsInt32(result, &cast))
                 return MConstant::New(alloc, Int32Value(cast));
         } else if (type() == MIRType::Float32) {
-            return MConstant::New(alloc, wasm::RawF32(float(result)));
+            return MConstant::NewRawFloat32(alloc, float(result));
         } else {
             MOZ_ASSERT(type() == MIRType::Double);
-            return MConstant::New(alloc, wasm::RawF64(result));
+            return MConstant::NewRawDouble(alloc, result);
         }
     }
 
     MDefinition* operand = lhs()->isConstant() ? rhs() : lhs();
     MConstant* constant = lhs()->isConstant() ? lhs()->toConstant() : rhs()->toConstant();
 
     if (operand->isToDouble() && operand->getOperand(0)->type() == MIRType::Int32) {
         // min(int32, cte >= INT32_MAX) = int32
@@ -4335,20 +4331,18 @@ MToDouble::foldsTo(TempAllocator& alloc)
 {
     MDefinition* input = getOperand(0);
     if (input->isBox())
         input = input->getOperand(0);
 
     if (input->type() == MIRType::Double)
         return input;
 
-    if (input->isConstant() && input->toConstant()->isTypeRepresentableAsDouble()) {
-        double out = input->toConstant()->numberToDouble();
-        return MConstant::New(alloc, wasm::RawF64(out));
-    }
+    if (input->isConstant() && input->toConstant()->isTypeRepresentableAsDouble())
+        return MConstant::NewRawDouble(alloc, input->toConstant()->numberToDouble());
 
     return this;
 }
 
 MDefinition*
 MToFloat32::foldsTo(TempAllocator& alloc)
 {
     MDefinition* input = getOperand(0);
@@ -4361,20 +4355,18 @@ MToFloat32::foldsTo(TempAllocator& alloc
     // If x is a Float32, Float32(Double(x)) == x
     if (!mustPreserveNaN_ &&
         input->isToDouble() &&
         input->toToDouble()->input()->type() == MIRType::Float32)
     {
         return input->toToDouble()->input();
     }
 
-    if (input->isConstant() && input->toConstant()->isTypeRepresentableAsDouble()) {
-        float out = float(input->toConstant()->numberToDouble());
-        return MConstant::New(alloc, wasm::RawF32(out));
-    }
+    if (input->isConstant() && input->toConstant()->isTypeRepresentableAsDouble())
+        return MConstant::NewRawFloat32(alloc, float(input->toConstant()->numberToDouble()));
 
     return this;
 }
 
 MDefinition*
 MToString::foldsTo(TempAllocator& alloc)
 {
     MDefinition* in = input();
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -1576,18 +1576,18 @@ class MConstant : public MNullaryInstruc
 
   public:
     INSTRUCTION_HEADER(Constant)
     static MConstant* New(TempAllocator& alloc, const Value& v,
                           CompilerConstraintList* constraints = nullptr);
     static MConstant* New(TempAllocator::Fallible alloc, const Value& v,
                           CompilerConstraintList* constraints = nullptr);
     static MConstant* New(TempAllocator& alloc, const Value& v, MIRType type);
-    static MConstant* New(TempAllocator& alloc, wasm::RawF32 bits);
-    static MConstant* New(TempAllocator& alloc, wasm::RawF64 bits);
+    static MConstant* NewRawFloat32(TempAllocator& alloc, float f);
+    static MConstant* NewRawDouble(TempAllocator& alloc, double d);
     static MConstant* NewFloat32(TempAllocator& alloc, double d);
     static MConstant* NewInt64(TempAllocator& alloc, int64_t i);
     static MConstant* NewConstraintlessObject(TempAllocator& alloc, JSObject* v);
     static MConstant* Copy(TempAllocator& alloc, MConstant* src) {
         return new(alloc) MConstant(*src);
     }
 
     // Try to convert this constant to boolean, similar to js::ToBoolean.
@@ -1645,32 +1645,24 @@ class MConstant : public MNullaryInstruc
     }
     int64_t toInt64() const {
         MOZ_ASSERT(type() == MIRType::Int64);
         return payload_.i64;
     }
     bool isInt32(int32_t i) const {
         return type() == MIRType::Int32 && payload_.i32 == i;
     }
-    double toDouble() const {
+    const double& toDouble() const {
         MOZ_ASSERT(type() == MIRType::Double);
         return payload_.d;
     }
-    wasm::RawF64 toRawF64() const {
-        MOZ_ASSERT(type() == MIRType::Double);
-        return wasm::RawF64::fromBits(payload_.i64);
-    }
-    float toFloat32() const {
+    const float& toFloat32() const {
         MOZ_ASSERT(type() == MIRType::Float32);
         return payload_.f;
     }
-    wasm::RawF32 toRawF32() const {
-        MOZ_ASSERT(type() == MIRType::Float32);
-        return wasm::RawF32::fromBits(payload_.i32);
-    }
     JSString* toString() const {
         MOZ_ASSERT(type() == MIRType::String);
         return payload_.str;
     }
     JS::Symbol* toSymbol() const {
         MOZ_ASSERT(type() == MIRType::Symbol);
         return payload_.sym;
     }
--- a/js/src/jit/arm/Assembler-arm.cpp
+++ b/js/src/jit/arm/Assembler-arm.cpp
@@ -2205,35 +2205,33 @@ Assembler::as_BranchPool(uint32_t value,
 #ifdef JS_DISASM_ARM
     if (documentation)
         spewTarget(documentation);
 #endif
     return ret;
 }
 
 BufferOffset
-Assembler::as_FImm64Pool(VFPRegister dest, wasm::RawF64 value, Condition c)
+Assembler::as_FImm64Pool(VFPRegister dest, double d, Condition c)
 {
     MOZ_ASSERT(dest.isDouble());
     PoolHintPun php;
     php.phd.init(0, c, PoolHintData::PoolVDTR, dest);
-    uint64_t d = value.bits();
     return allocEntry(1, 2, (uint8_t*)&php.raw, (uint8_t*)&d);
 }
 
 BufferOffset
-Assembler::as_FImm32Pool(VFPRegister dest, wasm::RawF32 value, Condition c)
+Assembler::as_FImm32Pool(VFPRegister dest, float f, Condition c)
 {
     // Insert floats into the double pool as they have the same limitations on
     // immediate offset. This wastes 4 bytes padding per float. An alternative
     // would be to have a separate pool for floats.
     MOZ_ASSERT(dest.isSingle());
     PoolHintPun php;
     php.phd.init(0, c, PoolHintData::PoolVDTR, dest);
-    uint32_t f = value.bits();
     return allocEntry(1, 1, (uint8_t*)&php.raw, (uint8_t*)&f);
 }
 
 // Pool callbacks stuff:
 void
 Assembler::InsertIndexIntoTag(uint8_t* load_, uint32_t index)
 {
     uint32_t* load = (uint32_t*)load_;
--- a/js/src/jit/arm/Assembler-arm.h
+++ b/js/src/jit/arm/Assembler-arm.h
@@ -1546,19 +1546,19 @@ class Assembler : public AssemblerShared
     // Load a 32 bit immediate from a pool into a register.
     BufferOffset as_Imm32Pool(Register dest, uint32_t value, Condition c = Always);
     // Make a patchable jump that can target the entire 32 bit address space.
     BufferOffset as_BranchPool(uint32_t value, RepatchLabel* label,
                                ARMBuffer::PoolEntry* pe = nullptr, Condition c = Always,
                                Label* documentation = nullptr);
 
     // Load a 64 bit floating point immediate from a pool into a register.
-    BufferOffset as_FImm64Pool(VFPRegister dest, wasm::RawF64 value, Condition c = Always);
+    BufferOffset as_FImm64Pool(VFPRegister dest, double value, Condition c = Always);
     // Load a 32 bit floating point immediate from a pool into a register.
-    BufferOffset as_FImm32Pool(VFPRegister dest, wasm::RawF32 value, Condition c = Always);
+    BufferOffset as_FImm32Pool(VFPRegister dest, float value, Condition c = Always);
 
     // Atomic instructions: ldrex, ldrexh, ldrexb, strex, strexh, strexb.
     //
     // The halfword and byte versions are available from ARMv6K forward.
     //
     // The word versions are available from ARMv6 forward and can be used to
     // implement the halfword and byte versions on older systems.
 
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -20,16 +20,17 @@
 
 #include "jit/MacroAssembler-inl.h"
 
 using namespace js;
 using namespace jit;
 
 using mozilla::Abs;
 using mozilla::BitwiseCast;
+using mozilla::IsPositiveZero;
 
 bool
 isValueDTRDCandidate(ValueOperand& val)
 {
     // In order to be used for a DTRD memory function, the two target registers
     // need to be a) Adjacent, with the tag larger than the payload, and b)
     // Aligned to a multiple of two.
     if ((val.typeReg().code() != (val.payloadReg().code() + 1)))
@@ -1522,29 +1523,29 @@ MacroAssemblerARM::ma_vsqrt(FloatRegiste
 
 void
 MacroAssemblerARM::ma_vsqrt_f32(FloatRegister src, FloatRegister dest, Condition cc)
 {
     as_vsqrt(VFPRegister(dest).singleOverlay(), VFPRegister(src).singleOverlay(), cc);
 }
 
 static inline uint32_t
-DoubleHighWord(wasm::RawF64 value)
-{
-    return static_cast<uint32_t>(value.bits() >> 32);
+DoubleHighWord(double d)
+{
+    return static_cast<uint32_t>(BitwiseCast<uint64_t>(d) >> 32);
 }
 
 static inline uint32_t
-DoubleLowWord(wasm::RawF64 value)
-{
-    return value.bits() & uint32_t(0xffffffff);
-}
-
-void
-MacroAssemblerARM::ma_vimm(wasm::RawF64 value, FloatRegister dest, Condition cc)
+DoubleLowWord(double d)
+{
+    return static_cast<uint32_t>(BitwiseCast<uint64_t>(d)) & uint32_t(0xffffffff);
+}
+
+void
+MacroAssemblerARM::ma_vimm(double value, FloatRegister dest, Condition cc)
 {
     if (HasVFPv3()) {
         if (DoubleLowWord(value) == 0) {
             if (DoubleHighWord(value) == 0) {
                 // To zero a register, load 1.0, then execute dN <- dN - dN
                 as_vimm(dest, VFPImm::One, cc);
                 as_vsub(dest, dest, dest, cc);
                 return;
@@ -1557,35 +1558,35 @@ MacroAssemblerARM::ma_vimm(wasm::RawF64 
             }
         }
     }
     // Fall back to putting the value in a pool.
     as_FImm64Pool(dest, value, cc);
 }
 
 void
-MacroAssemblerARM::ma_vimm_f32(wasm::RawF32 value, FloatRegister dest, Condition cc)
+MacroAssemblerARM::ma_vimm_f32(float value, FloatRegister dest, Condition cc)
 {
     VFPRegister vd = VFPRegister(dest).singleOverlay();
     if (HasVFPv3()) {
-        if (value.bits() == 0) {
+        if (IsPositiveZero(value)) {
             // To zero a register, load 1.0, then execute sN <- sN - sN.
             as_vimm(vd, VFPImm::One, cc);
             as_vsub(vd, vd, vd, cc);
             return;
         }
 
         // Note that the vimm immediate float32 instruction encoding differs
         // from the vimm immediate double encoding, but this difference matches
         // the difference in the floating point formats, so it is possible to
         // convert the float32 to a double and then use the double encoding
         // paths. It is still necessary to firstly check that the double low
         // word is zero because some float32 numbers set these bits and this can
         // not be ignored.
-        wasm::RawF64 doubleValue(double(value.fp()));
+        double doubleValue(value);
         if (DoubleLowWord(doubleValue) == 0) {
             VFPImm enc(DoubleHighWord(doubleValue));
             if (enc.isValid()) {
                 as_vimm(vd, enc, cc);
                 return;
             }
         }
     }
@@ -3157,22 +3158,16 @@ MacroAssemblerARMCompat::int32ValueToFlo
              vfpdest.sintOverlay(), CoreToFloat);
     // Convert the value to a float.
     as_vcvt(vfpdest, vfpdest.sintOverlay());
 }
 
 void
 MacroAssemblerARMCompat::loadConstantFloat32(float f, FloatRegister dest)
 {
-    loadConstantFloat32(wasm::RawF32(f), dest);
-}
-
-void
-MacroAssemblerARMCompat::loadConstantFloat32(wasm::RawF32 f, FloatRegister dest)
-{
     ma_vimm_f32(f, dest);
 }
 
 void
 MacroAssemblerARMCompat::loadInt32OrDouble(const Address& src, FloatRegister dest)
 {
     Label notInt32, end;
 
@@ -3227,22 +3222,16 @@ MacroAssemblerARMCompat::loadInt32OrDoub
     ma_alu(base, lsl(index, shift), scratch, OpAdd);
     ma_vldr(VFPAddr(scratch, VFPOffImm(0)), dest);
     bind(&end);
 }
 
 void
 MacroAssemblerARMCompat::loadConstantDouble(double dp, FloatRegister dest)
 {
-    loadConstantDouble(wasm::RawF64(dp), dest);
-}
-
-void
-MacroAssemblerARMCompat::loadConstantDouble(wasm::RawF64 dp, FloatRegister dest)
-{
     ma_vimm(dp, dest);
 }
 
 // Treat the value as a boolean, and set condition codes accordingly.
 Assembler::Condition
 MacroAssemblerARMCompat::testInt32Truthy(bool truthy, const ValueOperand& operand)
 {
     ma_tst(operand.payloadReg(), operand.payloadReg());
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -371,18 +371,18 @@ class MacroAssemblerARM : public Assembl
     void ma_vmov(FloatRegister src, FloatRegister dest, Condition cc = Always);
     void ma_vmov_f32(FloatRegister src, FloatRegister dest, Condition cc = Always);
     void ma_vabs(FloatRegister src, FloatRegister dest, Condition cc = Always);
     void ma_vabs_f32(FloatRegister src, FloatRegister dest, Condition cc = Always);
 
     void ma_vsqrt(FloatRegister src, FloatRegister dest, Condition cc = Always);
     void ma_vsqrt_f32(FloatRegister src, FloatRegister dest, Condition cc = Always);
 
-    void ma_vimm(wasm::RawF64 value, FloatRegister dest, Condition cc = Always);
-    void ma_vimm_f32(wasm::RawF32 value, FloatRegister dest, Condition cc = Always);
+    void ma_vimm(double value, FloatRegister dest, Condition cc = Always);
+    void ma_vimm_f32(float value, FloatRegister dest, Condition cc = Always);
 
     void ma_vcmp(FloatRegister src1, FloatRegister src2, Condition cc = Always);
     void ma_vcmp_f32(FloatRegister src1, FloatRegister src2, Condition cc = Always);
     void ma_vcmpz(FloatRegister src1, Condition cc = Always);
     void ma_vcmpz_f32(FloatRegister src1, Condition cc = Always);
 
     void ma_vadd_f32(FloatRegister src1, FloatRegister src2, FloatRegister dst);
     void ma_vsub_f32(FloatRegister src1, FloatRegister src2, FloatRegister dst);
@@ -788,28 +788,26 @@ class MacroAssemblerARMCompat : public M
     }
 
     void boolValueToDouble(const ValueOperand& operand, FloatRegister dest);
     void int32ValueToDouble(const ValueOperand& operand, FloatRegister dest);
     void loadInt32OrDouble(const Address& src, FloatRegister dest);
     void loadInt32OrDouble(Register base, Register index,
                            FloatRegister dest, int32_t shift = defaultShift);
     void loadConstantDouble(double dp, FloatRegister dest);
-    void loadConstantDouble(wasm::RawF64 dp, FloatRegister dest);
 
     // Treat the value as a boolean, and set condition codes accordingly.
     Condition testInt32Truthy(bool truthy, const ValueOperand& operand);
     Condition testBooleanTruthy(bool truthy, const ValueOperand& operand);
     Condition testDoubleTruthy(bool truthy, FloatRegister reg);
     Condition testStringTruthy(bool truthy, const ValueOperand& value);
 
     void boolValueToFloat32(const ValueOperand& operand, FloatRegister dest);
     void int32ValueToFloat32(const ValueOperand& operand, FloatRegister dest);
     void loadConstantFloat32(float f, FloatRegister dest);
-    void loadConstantFloat32(wasm::RawF32 f, FloatRegister dest);
 
     void moveValue(const Value& val, Register type, Register data);
 
     CodeOffsetJump jumpWithPatch(RepatchLabel* label, Condition cond = Always,
                                  Label* documentation = nullptr);
     CodeOffsetJump backedgeJump(RepatchLabel* label, Label* documentation) {
         return jumpWithPatch(label, Always, documentation);
     }
--- a/js/src/jit/arm64/MacroAssembler-arm64.h
+++ b/js/src/jit/arm64/MacroAssembler-arm64.h
@@ -1398,22 +1398,16 @@ class MacroAssemblerCompat : public vixl
 
     void boolValueToFloat32(const ValueOperand& operand, FloatRegister dest) {
         convertInt32ToFloat32(operand.valueReg(), dest);
     }
     void int32ValueToFloat32(const ValueOperand& operand, FloatRegister dest) {
         convertInt32ToFloat32(operand.valueReg(), dest);
     }
 
-    void loadConstantDouble(wasm::RawF64 d, FloatRegister dest) {
-        loadConstantDouble(d.fp(), dest);
-    }
-    void loadConstantFloat32(wasm::RawF32 f, FloatRegister dest) {
-        loadConstantFloat32(f.fp(), dest);
-    }
     void loadConstantDouble(double d, FloatRegister dest) {
         Fmov(ARMFPRegister(dest, 64), d);
     }
     void loadConstantFloat32(float f, FloatRegister dest) {
         Fmov(ARMFPRegister(dest, 32), f);
     }
 
     // Register-based tests.
--- a/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp
+++ b/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp
@@ -1003,25 +1003,16 @@ MacroAssemblerMIPSShared::ma_lis(FloatRe
 {
     Imm32 imm(mozilla::BitwiseCast<uint32_t>(value));
 
     ma_li(ScratchRegister, imm);
     moveToFloat32(ScratchRegister, dest);
 }
 
 void
-MacroAssemblerMIPSShared::ma_lis(FloatRegister dest, wasm::RawF32 value)
-{
-    Imm32 imm(value.bits());
-
-    ma_li(ScratchRegister, imm);
-    moveToFloat32(ScratchRegister, dest);
-}
-
-void
 MacroAssemblerMIPSShared::ma_liNegZero(FloatRegister dest)
 {
     moveToDoubleLo(zero, dest);
     ma_li(ScratchRegister, Imm32(INT_MIN));
     asMasm().moveToDoubleHi(ScratchRegister, dest);
 }
 
 void
--- a/js/src/jit/mips-shared/MacroAssembler-mips-shared.h
+++ b/js/src/jit/mips-shared/MacroAssembler-mips-shared.h
@@ -159,17 +159,16 @@ class MacroAssemblerMIPSShared : public 
     void ma_b(Register lhs, T rhs, wasm::TrapDesc target, Condition c,
               JumpKind jumpKind = LongJump);
 
     void ma_b(Label* l, JumpKind jumpKind = LongJump);
     void ma_b(wasm::TrapDesc target, JumpKind jumpKind = LongJump);
 
     // fp instructions
     void ma_lis(FloatRegister dest, float value);
-    void ma_lis(FloatRegister dest, wasm::RawF32 value);
     void ma_liNegZero(FloatRegister dest);
 
     void ma_sd(FloatRegister fd, BaseIndex address);
     void ma_ss(FloatRegister fd, BaseIndex address);
 
     //FP branches
     void ma_bc1s(FloatRegister lhs, FloatRegister rhs, Label* label, DoubleCondition c,
                  JumpKind jumpKind = LongJump, FPConditionBit fcc = FCC0);
--- a/js/src/jit/mips32/MacroAssembler-mips32.cpp
+++ b/js/src/jit/mips32/MacroAssembler-mips32.cpp
@@ -1397,22 +1397,16 @@ MacroAssemblerMIPSCompat::int32ValueToFl
 
 void
 MacroAssemblerMIPSCompat::loadConstantFloat32(float f, FloatRegister dest)
 {
     ma_lis(dest, f);
 }
 
 void
-MacroAssemblerMIPSCompat::loadConstantFloat32(wasm::RawF32 f, FloatRegister dest)
-{
-    ma_lis(dest, f);
-}
-
-void
 MacroAssemblerMIPSCompat::loadInt32OrDouble(const Address& src, FloatRegister dest)
 {
     Label notInt32, end;
     // If it's an int, convert it to double.
     ma_lw(SecondScratchReg, Address(src.base, src.offset + TAG_OFFSET));
     asMasm().branchTestInt32(Assembler::NotEqual, SecondScratchReg, &notInt32);
     ma_lw(SecondScratchReg, Address(src.base, src.offset + PAYLOAD_OFFSET));
     convertInt32ToDouble(SecondScratchReg, dest);
@@ -1452,44 +1446,16 @@ MacroAssemblerMIPSCompat::loadInt32OrDou
 }
 
 void
 MacroAssemblerMIPSCompat::loadConstantDouble(double dp, FloatRegister dest)
 {
     ma_lid(dest, dp);
 }
 
-void
-MacroAssemblerMIPSCompat::loadConstantDouble(wasm::RawF64 d, FloatRegister dest)
-{
-    struct DoubleStruct {
-        uint32_t lo;
-        uint32_t hi;
-    } ;
-    DoubleStruct intStruct = mozilla::BitwiseCast<DoubleStruct>(d.bits());
-
-    // put hi part of 64 bit value into the odd register
-    if (intStruct.hi == 0) {
-        moveToDoubleHi(zero, dest);
-    } else {
-        ScratchRegisterScope scratch(asMasm());
-        ma_li(scratch, Imm32(intStruct.hi));
-        moveToDoubleHi(scratch, dest);
-    }
-
-    // put low part of 64 bit value into the even register
-    if (intStruct.lo == 0) {
-        moveToDoubleLo(zero, dest);
-    } else {
-        ScratchRegisterScope scratch(asMasm());
-        ma_li(scratch, Imm32(intStruct.lo));
-        moveToDoubleLo(scratch, dest);
-    }
-}
-
 Register
 MacroAssemblerMIPSCompat::extractObject(const Address& address, Register scratch)
 {
     ma_lw(scratch, Address(address.base, address.offset + PAYLOAD_OFFSET));
     return scratch;
 }
 
 Register
--- a/js/src/jit/mips32/MacroAssembler-mips32.h
+++ b/js/src/jit/mips32/MacroAssembler-mips32.h
@@ -355,22 +355,20 @@ class MacroAssemblerMIPSCompat : public 
     }
 
     void boolValueToDouble(const ValueOperand& operand, FloatRegister dest);
     void int32ValueToDouble(const ValueOperand& operand, FloatRegister dest);
     void loadInt32OrDouble(const Address& address, FloatRegister dest);
     void loadInt32OrDouble(Register base, Register index,
                            FloatRegister dest, int32_t shift = defaultShift);
     void loadConstantDouble(double dp, FloatRegister dest);
-    void loadConstantDouble(wasm::RawF64 d, FloatRegister dest);
 
     void boolValueToFloat32(const ValueOperand& operand, FloatRegister dest);
     void int32ValueToFloat32(const ValueOperand& operand, FloatRegister dest);
     void loadConstantFloat32(float f, FloatRegister dest);
-    void loadConstantFloat32(wasm::RawF32 f, FloatRegister dest);
 
     void testNullSet(Condition cond, const ValueOperand& value, Register dest);
 
     void testObjectSet(Condition cond, const ValueOperand& value, Register dest);
 
     void testUndefinedSet(Condition cond, const ValueOperand& value, Register dest);
 
     // higher level tag testing code
--- a/js/src/jit/mips64/MacroAssembler-mips64.cpp
+++ b/js/src/jit/mips64/MacroAssembler-mips64.cpp
@@ -1660,22 +1660,16 @@ MacroAssemblerMIPS64Compat::int32ValueTo
 
 void
 MacroAssemblerMIPS64Compat::loadConstantFloat32(float f, FloatRegister dest)
 {
     ma_lis(dest, f);
 }
 
 void
-MacroAssemblerMIPS64Compat::loadConstantFloat32(wasm::RawF32 f, FloatRegister dest)
-{
-    ma_lis(dest, f);
-}
-
-void
 MacroAssemblerMIPS64Compat::loadInt32OrDouble(const Address& src, FloatRegister dest)
 {
     Label notInt32, end;
     // If it's an int, convert it to double.
     loadPtr(Address(src.base, src.offset), ScratchRegister);
     ma_dsrl(SecondScratchReg, ScratchRegister, Imm32(JSVAL_TAG_SHIFT));
     asMasm().branchTestInt32(Assembler::NotEqual, SecondScratchReg, &notInt32);
     loadPtr(Address(src.base, src.offset), SecondScratchReg);
@@ -1715,25 +1709,16 @@ MacroAssemblerMIPS64Compat::loadInt32OrD
 }
 
 void
 MacroAssemblerMIPS64Compat::loadConstantDouble(double dp, FloatRegister dest)
 {
     ma_lid(dest, dp);
 }
 
-void
-MacroAssemblerMIPS64Compat::loadConstantDouble(wasm::RawF64 d, FloatRegister dest)
-{
-    ImmWord imm(d.bits());
-
-    ma_li(ScratchRegister, imm);
-    moveToDouble(ScratchRegister, dest);
-}
-
 Register
 MacroAssemblerMIPS64Compat::extractObject(const Address& address, Register scratch)
 {
     loadPtr(Address(address.base, address.offset), scratch);
     ma_dext(scratch, scratch, Imm32(0), Imm32(JSVAL_TAG_SHIFT));
     return scratch;
 }
 
--- a/js/src/jit/mips64/MacroAssembler-mips64.h
+++ b/js/src/jit/mips64/MacroAssembler-mips64.h
@@ -404,22 +404,20 @@ class MacroAssemblerMIPS64Compat : publi
         return scratch;
     }
 
     void boolValueToDouble(const ValueOperand& operand, FloatRegister dest);
     void int32ValueToDouble(const ValueOperand& operand, FloatRegister dest);
     void loadInt32OrDouble(const Address& src, FloatRegister dest);
     void loadInt32OrDouble(const BaseIndex& addr, FloatRegister dest);
     void loadConstantDouble(double dp, FloatRegister dest);
-    void loadConstantDouble(wasm::RawF64 d, FloatRegister dest);
 
     void boolValueToFloat32(const ValueOperand& operand, FloatRegister dest);
     void int32ValueToFloat32(const ValueOperand& operand, FloatRegister dest);
     void loadConstantFloat32(float f, FloatRegister dest);
-    void loadConstantFloat32(wasm::RawF32 f, FloatRegister dest);
 
     void testNullSet(Condition cond, const ValueOperand& value, Register dest);
 
     void testObjectSet(Condition cond, const ValueOperand& value, Register dest);
 
     void testUndefinedSet(Condition cond, const ValueOperand& value, Register dest);
 
     // higher level tag testing code
--- a/js/src/jit/none/MacroAssembler-none.h
+++ b/js/src/jit/none/MacroAssembler-none.h
@@ -388,18 +388,16 @@ class MacroAssemblerNone : public Assemb
 
     void boolValueToDouble(ValueOperand, FloatRegister) { MOZ_CRASH(); }
     void boolValueToFloat32(ValueOperand, FloatRegister) { MOZ_CRASH(); }
     void int32ValueToDouble(ValueOperand, FloatRegister) { MOZ_CRASH(); }
     void int32ValueToFloat32(ValueOperand, FloatRegister) { MOZ_CRASH(); }
 
     void loadConstantDouble(double, FloatRegister) { MOZ_CRASH(); }
     void loadConstantFloat32(float, FloatRegister) { MOZ_CRASH(); }
-    void loadConstantDouble(wasm::RawF64, FloatRegister) { MOZ_CRASH(); }
-    void loadConstantFloat32(wasm::RawF32, FloatRegister) { MOZ_CRASH(); }
     Condition testInt32Truthy(bool, ValueOperand) { MOZ_CRASH(); }
     Condition testStringTruthy(bool, ValueOperand) { MOZ_CRASH(); }
 
     template <typename T> void loadUnboxedValue(T, MIRType, AnyRegister) { MOZ_CRASH(); }
     template <typename T> void storeUnboxedValue(const ConstantOrRegister&, MIRType, T, MIRType) { MOZ_CRASH(); }
     template <typename T> void storeUnboxedPayload(ValueOperand value, T, size_t) { MOZ_CRASH(); }
 
     void convertUInt32ToDouble(Register, FloatRegister) { MOZ_CRASH(); }
--- a/js/src/jit/shared/LIR-shared.h
+++ b/js/src/jit/shared/LIR-shared.h
@@ -853,40 +853,40 @@ class LPointer : public LInstructionHelp
         MOZ_ASSERT(kind() == GC_THING);
         return (gc::Cell*) ptr_;
     }
 };
 
 // Constant double.
 class LDouble : public LInstructionHelper<1, 0, 0>
 {
-    wasm::RawF64 d_;
+    double d_;
   public:
     LIR_HEADER(Double);
 
-    explicit LDouble(wasm::RawF64 d) : d_(d)
+    explicit LDouble(double d) : d_(d)
     { }
 
-    wasm::RawF64 getDouble() const {
+    const double& getDouble() const {
         return d_;
     }
 };
 
 // Constant float32.
 class LFloat32 : public LInstructionHelper<1, 0, 0>
 {
-    wasm::RawF32 f_;
+    float f_;
   public:
     LIR_HEADER(Float32);
 
-    explicit LFloat32(wasm::RawF32 f)
+    explicit LFloat32(float f)
       : f_(f)
     { }
 
-    wasm::RawF32 getFloat() const {
+    const float& getFloat() const {
         return f_;
     }
 };
 
 // Constant 128-bit SIMD integer vector (8x16, 16x8, 32x4).
 // Also used for Bool32x4, Bool16x8, etc.
 class LSimd128Int : public LInstructionHelper<1, 0, 0>
 {
--- a/js/src/jit/shared/Lowering-shared.cpp
+++ b/js/src/jit/shared/Lowering-shared.cpp
@@ -76,20 +76,20 @@ LIRGeneratorShared::visitConstant(MConst
 {
     if (!IsFloatingPointType(ins->type()) && ins->canEmitAtUses()) {
         emitAtUses(ins);
         return;
     }
 
     switch (ins->type()) {
       case MIRType::Double:
-        define(new(alloc()) LDouble(ins->toRawF64()), ins);
+        define(new(alloc()) LDouble(ins->toDouble()), ins);
         break;
       case MIRType::Float32:
-        define(new(alloc()) LFloat32(ins->toRawF32()), ins);
+        define(new(alloc()) LFloat32(ins->toFloat32()), ins);
         break;
       case MIRType::Boolean:
         define(new(alloc()) LInteger(ins->toBoolean()), ins);
         break;
       case MIRType::Int32:
         define(new(alloc()) LInteger(ins->toInt32()), ins);
         break;
       case MIRType::Int64:
--- a/js/src/jit/shared/Lowering-shared.h
+++ b/js/src/jit/shared/Lowering-shared.h
@@ -266,20 +266,20 @@ class LIRGeneratorShared : public MDefin
     // Marks this instruction as needing to call into either the VM or GC. This
     // function may build a snapshot that captures the result of its own
     // instruction, and as such, should generally be called after define*().
     void assignSafepoint(LInstruction* ins, MInstruction* mir,
                          BailoutKind kind = Bailout_DuringVMCall);
 
   public:
     void lowerConstantDouble(double d, MInstruction* mir) {
-        define(new(alloc()) LDouble(wasm::RawF64(d)), mir);
+        define(new(alloc()) LDouble(d), mir);
     }
     void lowerConstantFloat32(float f, MInstruction* mir) {
-        define(new(alloc()) LFloat32(wasm::RawF32(f)), mir);
+        define(new(alloc()) LFloat32(f), mir);
     }
 
     void visitConstant(MConstant* ins) override;
 
     // Whether to generate typed reads for element accesses with hole checks.
     static bool allowTypedElementHoleCheck() {
         return false;
     }
--- a/js/src/jit/x64/MacroAssembler-x64.cpp
+++ b/js/src/jit/x64/MacroAssembler-x64.cpp
@@ -14,34 +14,34 @@
 #include "jit/MoveEmitter.h"
 
 #include "jit/MacroAssembler-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 void
-MacroAssemblerX64::loadConstantDouble(wasm::RawF64 d, FloatRegister dest)
+MacroAssemblerX64::loadConstantDouble(double d, FloatRegister dest)
 {
     if (maybeInlineDouble(d, dest))
         return;
     Double* dbl = getDouble(d);
     if (!dbl)
         return;
     // The constants will be stored in a pool appended to the text (see
     // finish()), so they will always be a fixed distance from the
     // instructions which reference them. This allows the instructions to use
     // PC-relative addressing. Use "jump" label support code, because we need
     // the same PC-relative address patching that jumps use.
     JmpSrc j = masm.vmovsd_ripr(dest.encoding());
     propagateOOM(dbl->uses.append(CodeOffset(j.offset())));
 }
 
 void
-MacroAssemblerX64::loadConstantFloat32(wasm::RawF32 f, FloatRegister dest)
+MacroAssemblerX64::loadConstantFloat32(float f, FloatRegister dest)
 {
     if (maybeInlineFloat(f, dest))
         return;
     Float* flt = getFloat(f);
     if (!flt)
         return;
     // See comment in loadConstantDouble
     JmpSrc j = masm.vmovss_ripr(dest.encoding());
@@ -56,28 +56,16 @@ MacroAssemblerX64::loadConstantSimd128In
     SimdData* val = getSimdData(v);
     if (!val)
         return;
     JmpSrc j = masm.vmovdqa_ripr(dest.encoding());
     propagateOOM(val->uses.append(CodeOffset(j.offset())));
 }
 
 void
-MacroAssemblerX64::loadConstantFloat32(float f, FloatRegister dest)
-{
-    loadConstantFloat32(wasm::RawF32(f), dest);
-}
-
-void
-MacroAssemblerX64::loadConstantDouble(double d, FloatRegister dest)
-{
-    loadConstantDouble(wasm::RawF64(d), dest);
-}
-
-void
 MacroAssemblerX64::loadConstantSimd128Float(const SimdConstant&v, FloatRegister dest)
 {
     if (maybeInlineSimd128Float(v, dest))
         return;
     SimdData* val = getSimdData(v);
     if (!val)
         return;
     JmpSrc j = masm.vmovaps_ripr(dest.encoding());
@@ -260,24 +248,24 @@ MacroAssemblerX64::bindOffsets(const Mac
 
 void
 MacroAssemblerX64::finish()
 {
     if (!doubles_.empty())
         masm.haltingAlign(sizeof(double));
     for (const Double& d : doubles_) {
         bindOffsets(d.uses);
-        masm.int64Constant(d.value);
+        masm.doubleConstant(d.value);
     }
 
     if (!floats_.empty())
         masm.haltingAlign(sizeof(float));
     for (const Float& f : floats_) {
         bindOffsets(f.uses);
-        masm.int32Constant(f.value);
+        masm.floatConstant(f.value);
     }
 
     // SIMD memory values must be suitably aligned.
     if (!simds_.empty())
         masm.haltingAlign(SimdMemoryAlignment);
     for (const SimdData& v : simds_) {
         bindOffsets(v.uses);
         masm.simd128Constant(v.value.bytes());
--- a/js/src/jit/x64/MacroAssembler-x64.h
+++ b/js/src/jit/x64/MacroAssembler-x64.h
@@ -852,18 +852,16 @@ class MacroAssemblerX64 : public MacroAs
         convertInt32ToFloat32(operand.valueReg(), dest);
     }
     void int32ValueToFloat32(const ValueOperand& operand, FloatRegister dest) {
         convertInt32ToFloat32(operand.valueReg(), dest);
     }
 
     void loadConstantDouble(double d, FloatRegister dest);
     void loadConstantFloat32(float f, FloatRegister dest);
-    void loadConstantDouble(wasm::RawF64 d, FloatRegister dest);
-    void loadConstantFloat32(wasm::RawF32 f, FloatRegister dest);
 
     void loadConstantSimd128Int(const SimdConstant& v, FloatRegister dest);
     void loadConstantSimd128Float(const SimdConstant& v, FloatRegister dest);
 
     void convertInt64ToDouble(Register64 input, FloatRegister output);
     void convertInt64ToFloat32(Register64 input, FloatRegister output);
     static bool convertUInt64ToDoubleNeedsTemp();
     void convertUInt64ToDouble(Register64 input, FloatRegister output, Register temp);
--- a/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp
+++ b/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp
@@ -249,25 +249,25 @@ MacroAssemblerX86Shared::getConstant(con
         enoughMemory_ &= map.add(p, value, index);
         if (!enoughMemory_)
             return nullptr;
     }
     return &vec[index];
 }
 
 MacroAssemblerX86Shared::Float*
-MacroAssemblerX86Shared::getFloat(wasm::RawF32 f)
+MacroAssemblerX86Shared::getFloat(float f)
 {
-    return getConstant<Float, FloatMap>(f.bits(), floatMap_, floats_);
+    return getConstant<Float, FloatMap>(f, floatMap_, floats_);
 }
 
 MacroAssemblerX86Shared::Double*
-MacroAssemblerX86Shared::getDouble(wasm::RawF64 d)
+MacroAssemblerX86Shared::getDouble(double d)
 {
-    return getConstant<Double, DoubleMap>(d.bits(), doubleMap_, doubles_);
+    return getConstant<Double, DoubleMap>(d, doubleMap_, doubles_);
 }
 
 MacroAssemblerX86Shared::SimdData*
 MacroAssemblerX86Shared::getSimdData(const SimdConstant& v)
 {
     return getConstant<SimdData, SimdMap>(v, simdMap_, simds_);
 }
 
--- a/js/src/jit/x86-shared/MacroAssembler-x86-shared.h
+++ b/js/src/jit/x86-shared/MacroAssembler-x86-shared.h
@@ -61,42 +61,42 @@ class MacroAssemblerX86Shared : public A
         explicit Constant(const T& value) : value(value) {}
         Constant(Constant<T>&& other) : value(other.value), uses(mozilla::Move(other.uses)) {}
         explicit Constant(const Constant<T>&) = delete;
     };
 
     // Containers use SystemAllocPolicy since wasm releases memory after each
     // function is compiled, and these need to live until after all functions
     // are compiled.
-    using Double = Constant<uint64_t>;
+    using Double = Constant<double>;
     Vector<Double, 0, SystemAllocPolicy> doubles_;
-    typedef HashMap<uint64_t, size_t, DefaultHasher<uint64_t>, SystemAllocPolicy> DoubleMap;
+    typedef HashMap<double, size_t, DefaultHasher<double>, SystemAllocPolicy> DoubleMap;
     DoubleMap doubleMap_;
 
-    using Float = Constant<uint32_t>;
+    using Float = Constant<float>;
     Vector<Float, 0, SystemAllocPolicy> floats_;
-    typedef HashMap<uint32_t, size_t, DefaultHasher<uint32_t>, SystemAllocPolicy> FloatMap;
+    typedef HashMap<float, size_t, DefaultHasher<float>, SystemAllocPolicy> FloatMap;
     FloatMap floatMap_;
 
     struct SimdData : public Constant<SimdConstant> {
         explicit SimdData(SimdConstant d) : Constant<SimdConstant>(d) {}
         SimdData(SimdData&& d) : Constant<SimdConstant>(mozilla::Move(d)) {}
         explicit SimdData(const SimdData&) = delete;
         SimdConstant::Type type() const { return value.type(); }
     };
 
     Vector<SimdData, 0, SystemAllocPolicy> simds_;
     typedef HashMap<SimdConstant, size_t, SimdConstant, SystemAllocPolicy> SimdMap;
     SimdMap simdMap_;
 
     template<class T, class Map>
     T* getConstant(const typename T::Pod& value, Map& map, Vector<T, 0, SystemAllocPolicy>& vec);
 
-    Float* getFloat(wasm::RawF32 f);
-    Double* getDouble(wasm::RawF64 d);
+    Float* getFloat(float f);
+    Double* getDouble(double d);
     SimdData* getSimdData(const SimdConstant& v);
 
   public:
     using Assembler::call;
 
     MacroAssemblerX86Shared()
     { }
 
@@ -1205,37 +1205,37 @@ class MacroAssemblerX86Shared : public A
         convertInt32ToFloat32(dest, scratch);
         vucomiss(scratch, src);
         j(Assembler::Parity, fail);
         j(Assembler::NotEqual, fail);
     }
 
     inline void clampIntToUint8(Register reg);
 
-    bool maybeInlineDouble(wasm::RawF64 d, FloatRegister dest) {
+    bool maybeInlineDouble(double d, FloatRegister dest) {
         // Loading zero with xor is specially optimized in hardware.
-        if (d.bits() == 0) {
+        if (mozilla::IsPositiveZero(d)) {
             zeroDouble(dest);
             return true;
         }
 
         // It is also possible to load several common constants using vpcmpeqw
         // to get all ones and then vpsllq and vpsrlq to get zeros at the ends,
         // as described in "13.4 Generating constants" of
         // "2. Optimizing subroutines in assembly language" by Agner Fog, and as
         // previously implemented here. However, with x86 and x64 both using
         // constant pool loads for double constants, this is probably only
         // worthwhile in cases where a load is likely to be delayed.
 
         return false;
     }
 
-    bool maybeInlineFloat(wasm::RawF32 f, FloatRegister dest) {
+    bool maybeInlineFloat(float f, FloatRegister dest) {
         // See comment above
-        if (f.bits() == 0) {
+        if (mozilla::IsPositiveZero(f)) {
             zeroFloat32(dest);
             return true;
         }
         return false;
     }
 
     bool maybeInlineSimd128Int(const SimdConstant& v, const FloatRegister& dest) {
         static const SimdConstant zero = SimdConstant::SplatX4(0);
--- a/js/src/jit/x86/MacroAssembler-x86-inl.h
+++ b/js/src/jit/x86/MacroAssembler-x86-inl.h
@@ -179,17 +179,17 @@ MacroAssembler::add64(Imm64 imm, Registe
     }
     addl(imm.low(), dest.low);
     adcl(imm.hi(), dest.high);
 }
 
 void
 MacroAssembler::addConstantDouble(double d, FloatRegister dest)
 {
-    Double* dbl = getDouble(wasm::RawF64(d));
+    Double* dbl = getDouble(d);
     if (!dbl)
         return;
     masm.vaddsd_mr(nullptr, dest.encoding(), dest.encoding());
     propagateOOM(dbl->uses.append(CodeOffset(masm.size())));
 }
 
 CodeOffset
 MacroAssembler::add32ToPtrWithPatch(Register src, Register dest)
--- a/js/src/jit/x86/MacroAssembler-x86.cpp
+++ b/js/src/jit/x86/MacroAssembler-x86.cpp
@@ -106,52 +106,40 @@ MacroAssemblerX86::convertUInt64ToDouble
     // Add HI(dest) and LO(dest) in double and store it into LO(dest),
     //   LO(dest) = double(0x HHHHHHHH 00000000) + double(0x 00000000 LLLLLLLL)
     //            = double(0x HHHHHHHH LLLLLLLL)
     //            = double(src)
     vhaddpd(dest128, dest128);
 }
 
 void
-MacroAssemblerX86::loadConstantDouble(wasm::RawF64 d, FloatRegister dest)
+MacroAssemblerX86::loadConstantDouble(double d, FloatRegister dest)
 {
     if (maybeInlineDouble(d, dest))
         return;
     Double* dbl = getDouble(d);
     if (!dbl)
         return;
     masm.vmovsd_mr(nullptr, dest.encoding());
     propagateOOM(dbl->uses.append(CodeOffset(masm.size())));
 }
 
 void
-MacroAssemblerX86::loadConstantDouble(double d, FloatRegister dest)
-{
-    loadConstantDouble(wasm::RawF64(d), dest);
-}
-
-void
-MacroAssemblerX86::loadConstantFloat32(wasm::RawF32 f, FloatRegister dest)
+MacroAssemblerX86::loadConstantFloat32(float f, FloatRegister dest)
 {
     if (maybeInlineFloat(f, dest))
         return;
     Float* flt = getFloat(f);
     if (!flt)
         return;
     masm.vmovss_mr(nullptr, dest.encoding());
     propagateOOM(flt->uses.append(CodeOffset(masm.size())));
 }
 
 void
-MacroAssemblerX86::loadConstantFloat32(float f, FloatRegister dest)
-{
-    loadConstantFloat32(wasm::RawF32(f), dest);
-}
-
-void
 MacroAssemblerX86::loadConstantSimd128Int(const SimdConstant& v, FloatRegister dest)
 {
     if (maybeInlineSimd128Int(v, dest))
         return;
     SimdData* i4 = getSimdData(v);
     if (!i4)
         return;
     masm.vmovdqa_mr(nullptr, dest.encoding());
@@ -174,28 +162,28 @@ void
 MacroAssemblerX86::finish()
 {
     if (!doubles_.empty())
         masm.haltingAlign(sizeof(double));
     for (const Double& d : doubles_) {
         CodeOffset cst(masm.currentOffset());
         for (CodeOffset use : d.uses)
             addCodeLabel(CodeLabel(use, cst));
-        masm.int64Constant(d.value);
+        masm.doubleConstant(d.value);
         if (!enoughMemory_)
             return;
     }
 
     if (!floats_.empty())
         masm.haltingAlign(sizeof(float));
     for (const Float& f : floats_) {
         CodeOffset cst(masm.currentOffset());
         for (CodeOffset use : f.uses)
             addCodeLabel(CodeLabel(use, cst));
-        masm.int32Constant(f.value);
+        masm.floatConstant(f.value);
         if (!enoughMemory_)
             return;
     }
 
     // SIMD memory values must be suitably aligned.
     if (!simds_.empty())
         masm.haltingAlign(SimdMemoryAlignment);
     for (const SimdData& v : simds_) {
--- a/js/src/jit/x86/MacroAssembler-x86.h
+++ b/js/src/jit/x86/MacroAssembler-x86.h
@@ -774,18 +774,16 @@ class MacroAssemblerX86 : public MacroAs
         convertInt32ToDouble(operand.payloadReg(), dest);
     }
     void int32ValueToFloat32(const ValueOperand& operand, FloatRegister dest) {
         convertInt32ToFloat32(operand.payloadReg(), dest);
     }
 
     void loadConstantDouble(double d, FloatRegister dest);
     void loadConstantFloat32(float f, FloatRegister dest);
-    void loadConstantDouble(wasm::RawF64 d, FloatRegister dest);
-    void loadConstantFloat32(wasm::RawF32 f, FloatRegister dest);
 
     void loadConstantSimd128Int(const SimdConstant& v, FloatRegister dest);
     void loadConstantSimd128Float(const SimdConstant& v, FloatRegister dest);
 
     Condition testInt32Truthy(bool truthy, const ValueOperand& operand) {
         test32(operand.payloadReg(), operand.payloadReg());
         return truthy ? NonZero : Zero;
     }
--- a/js/src/wasm/AsmJS.cpp
+++ b/js/src/wasm/AsmJS.cpp
@@ -54,16 +54,17 @@ using namespace js::frontend;
 using namespace js::jit;
 using namespace js::wasm;
 
 using mozilla::CeilingLog2;
 using mozilla::Compression::LZ4;
 using mozilla::HashGeneric;
 using mozilla::IsNaN;
 using mozilla::IsNegativeZero;
+using mozilla::IsPositiveZero;
 using mozilla::IsPowerOfTwo;
 using mozilla::Maybe;
 using mozilla::Move;
 using mozilla::PodCopy;
 using mozilla::PodEqual;
 using mozilla::PodZero;
 using mozilla::PositiveInfinity;
 using JS::AsmJSOption;
@@ -883,24 +884,24 @@ class NumLit
         MOZ_ASSERT(which_ == Fixnum || which_ == NegativeInt || which_ == BigUnsigned);
         return u.scalar_.toInt32();
     }
 
     uint32_t toUint32() const {
         return (uint32_t)toInt32();
     }
 
-    RawF64 toDouble() const {
+    double toDouble() const {
         MOZ_ASSERT(which_ == Double);
-        return RawF64(u.scalar_.toDouble());
-    }
-
-    RawF32 toFloat() const {
+        return u.scalar_.toDouble();
+    }
+
+    float toFloat() const {
         MOZ_ASSERT(which_ == Float);
-        return RawF32(float(u.scalar_.toDouble()));
+        return float(u.scalar_.toDouble());
     }
 
     Value scalarValue() const {
         MOZ_ASSERT(which_ != OutOfRangeInt);
         return u.scalar_;
     }
 
     bool isSimd() const
@@ -923,19 +924,19 @@ class NumLit
     bool isZeroBits() const {
         MOZ_ASSERT(valid());
         switch (which()) {
           case NumLit::Fixnum:
           case NumLit::NegativeInt:
           case NumLit::BigUnsigned:
             return toInt32() == 0;
           case NumLit::Double:
-            return toDouble().bits() == 0;
+            return IsPositiveZero(toDouble());
           case NumLit::Float:
-            return toFloat().bits() == 0;
+            return IsPositiveZero(toFloat());
           case NumLit::Int8x16:
           case NumLit::Uint8x16:
           case NumLit::Bool8x16:
             return simdValue() == SimdConstant::SplatX16(0);
           case NumLit::Int16x8:
           case NumLit::Uint16x8:
           case NumLit::Bool16x8:
             return simdValue() == SimdConstant::SplatX8(0);
@@ -7511,24 +7512,24 @@ ValidateGlobalVariable(JSContext* cx, co
             return true;
           }
           case ValType::I64:
             MOZ_CRASH("int64");
           case ValType::F32: {
             float f;
             if (!RoundFloat32(cx, v, &f))
                 return false;
-            *val = Val(RawF32(f));
+            *val = Val(f);
             return true;
           }
           case ValType::F64: {
             double d;
             if (!ToNumber(cx, v, &d))
                 return false;
-            *val = Val(RawF64(d));
+            *val = Val(d);
             return true;
           }
           case ValType::I8x16: {
             SimdConstant simdConstant;
             if (!ToSimdConstant<Int8x16>(cx, v, &simdConstant))
                 return false;
             *val = Val(simdConstant.asInt8x16());
             return true;
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -872,46 +872,49 @@ class BaseCompiler
 
         union {
             RegI32   i32reg_;
             RegI64   i64reg_;
             RegF32   f32reg_;
             RegF64   f64reg_;
             int32_t  i32val_;
             int64_t  i64val_;
-            RawF32   f32val_;
-            RawF64   f64val_;
+            float    f32val_;
+            double   f64val_;
             uint32_t slot_;
             uint32_t offs_;
         };
 
         Stk() { kind_ = None; }
 
         Kind kind() const { return kind_; }
         bool isMem() const { return kind_ <= MemLast; }
 
         RegI32   i32reg() const { MOZ_ASSERT(kind_ == RegisterI32); return i32reg_; }
         RegI64   i64reg() const { MOZ_ASSERT(kind_ == RegisterI64); return i64reg_; }
         RegF32   f32reg() const { MOZ_ASSERT(kind_ == RegisterF32); return f32reg_; }
         RegF64   f64reg() const { MOZ_ASSERT(kind_ == RegisterF64); return f64reg_; }
         int32_t  i32val() const { MOZ_ASSERT(kind_ == ConstI32); return i32val_; }
         int64_t  i64val() const { MOZ_ASSERT(kind_ == ConstI64); return i64val_; }
-        RawF32   f32val() const { MOZ_ASSERT(kind_ == ConstF32); return f32val_; }
-        RawF64   f64val() const { MOZ_ASSERT(kind_ == ConstF64); return f64val_; }
+        // For these two, use an out-param instead of simply returning, to
+        // use the normal stack and not the x87 FP stack (which has effect on
+        // NaNs with the signaling bit set).
+        void     f32val(float* out) const { MOZ_ASSERT(kind_ == ConstF32); *out = f32val_; }
+        void     f64val(double* out) const { MOZ_ASSERT(kind_ == ConstF64); *out = f64val_; }
         uint32_t slot() const { MOZ_ASSERT(kind_ > MemLast && kind_ <= LocalLast); return slot_; }
         uint32_t offs() const { MOZ_ASSERT(isMem()); return offs_; }
 
         void setI32Reg(RegI32 r) { kind_ = RegisterI32; i32reg_ = r; }
         void setI64Reg(RegI64 r) { kind_ = RegisterI64; i64reg_ = r; }
         void setF32Reg(RegF32 r) { kind_ = RegisterF32; f32reg_ = r; }
         void setF64Reg(RegF64 r) { kind_ = RegisterF64; f64reg_ = r; }
         void setI32Val(int32_t v) { kind_ = ConstI32; i32val_ = v; }
         void setI64Val(int64_t v) { kind_ = ConstI64; i64val_ = v; }
-        void setF32Val(RawF32 v) { kind_ = ConstF32; f32val_ = v; }
-        void setF64Val(RawF64 v) { kind_ = ConstF64; f64val_ = v; }
+        void setF32Val(float v) { kind_ = ConstF32; f32val_ = v; }
+        void setF64Val(double v) { kind_ = ConstF64; f64val_ = v; }
         void setSlot(Kind k, uint32_t v) { MOZ_ASSERT(k > MemLast && k <= LocalLast); kind_ = k; slot_ = v; }
         void setOffs(Kind k, uint32_t v) { MOZ_ASSERT(k <= MemLast); kind_ = k; offs_ = v; }
     };
 
     Vector<Stk, 8, SystemAllocPolicy> stk_;
 
     Stk& push() {
         stk_.infallibleEmplaceBack(Stk());
@@ -1111,34 +1114,38 @@ class BaseCompiler
     }
 
     void loadRegisterI64(Register64 r, Stk& src) {
         if (src.i64reg() != r)
             masm.move64(src.i64reg(), r);
     }
 
     void loadConstF64(FloatRegister r, Stk &src) {
-        masm.loadConstantDouble(src.f64val(), r);
+        double d;
+        src.f64val(&d);
+        masm.loadConstantDouble(d, r);
     }
 
     void loadMemF64(FloatRegister r, Stk& src) {
         loadFromFrameF64(r, src.offs());
     }
 
     void loadLocalF64(FloatRegister r, Stk& src) {
         loadFromFrameF64(r, frameOffsetFromSlot(src.slot(), MIRType::Double));
     }
 
     void loadRegisterF64(FloatRegister r, Stk& src) {
         if (src.f64reg() != r)
             masm.moveDouble(src.f64reg(), r);
     }
 
     void loadConstF32(FloatRegister r, Stk &src) {
-        masm.loadConstantFloat32(src.f32val(), r);
+        float f;
+        src.f32val(&f);
+        masm.loadConstantFloat32(f, r);
     }
 
     void loadMemF32(FloatRegister r, Stk& src) {
         loadFromFrameF32(r, src.offs());
     }
 
     void loadLocalF32(FloatRegister r, Stk& src) {
         loadFromFrameF32(r, frameOffsetFromSlot(src.slot(), MIRType::Float32));
@@ -1442,22 +1449,22 @@ class BaseCompiler
         x.setI32Val(v);
     }
 
     void pushI64(int64_t v) {
         Stk& x = push();
         x.setI64Val(v);
     }
 
-    void pushF64(RawF64 v) {
+    void pushF64(double v) {
         Stk& x = push();
         x.setF64Val(v);
     }
 
-    void pushF32(RawF32 v) {
+    void pushF32(float v) {
         Stk& x = push();
         x.setF32Val(v);
     }
 
     // Push the local slot onto the stack.  The slot will not be read
     // here; it will be read when it is consumed, or when a side
     // effect to the slot forces its value to be saved.
 
@@ -7163,17 +7170,17 @@ BaseCompiler::emitBody()
             CHECK_NEXT(emitTeeStore(ValType::I64, Scalar::Int32));
           case uint16_t(Op::I64Store):
             CHECK_NEXT(emitStore(ValType::I64, Scalar::Int64));
           case uint16_t(Op::I64TeeStore):
             CHECK_NEXT(emitTeeStore(ValType::I64, Scalar::Int64));
 
           // F32
           case uint16_t(Op::F32Const): {
-            RawF32 f32;
+            float f32;
             CHECK(iter_.readF32Const(&f32));
             if (!deadCode_)
                 pushF32(f32);
             NEXT();
           }
           case uint16_t(Op::F32Add):
             CHECK_NEXT(emitBinary(emitAddF32, ValType::F32));
           case uint16_t(Op::F32Sub):
@@ -7232,17 +7239,17 @@ BaseCompiler::emitBody()
             CHECK_NEXT(emitBinary(emitCopysignF32, ValType::F32));
           case uint16_t(Op::F32Nearest):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::NearbyIntF, ValType::F32));
           case uint16_t(Op::F32Trunc):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::TruncF, ValType::F32));
 
           // F64
           case uint16_t(Op::F64Const): {
-            RawF64 f64;
+            double f64;
             CHECK(iter_.readF64Const(&f64));
             if (!deadCode_)
                 pushF64(f64);
             NEXT();
           }
           case uint16_t(Op::F64Add):
             CHECK_NEXT(emitBinary(emitAddF64, ValType::F64));
           case uint16_t(Op::F64Sub):
--- a/js/src/wasm/WasmBinaryIterator.h
+++ b/js/src/wasm/WasmBinaryIterator.h
@@ -303,26 +303,26 @@ class MOZ_STACK_CLASS OpIter : private P
         return true;
     }
     MOZ_MUST_USE bool readVarU64(uint64_t* out) {
         if (Validate)
             return d_.readVarU64(out);
         *out = d_.uncheckedReadVarU64();
         return true;
     }
-    MOZ_MUST_USE bool readFixedF32(RawF32* out) {
+    MOZ_MUST_USE bool readFixedF32(float* out) {
         if (Validate)
             return d_.readFixedF32(out);
-        *out = d_.uncheckedReadFixedF32();
+        d_.uncheckedReadFixedF32(out);
         return true;
     }
-    MOZ_MUST_USE bool readFixedF64(RawF64* out) {
+    MOZ_MUST_USE bool readFixedF64(double* out) {
         if (Validate)
             return d_.readFixedF64(out);
-        *out = d_.uncheckedReadFixedF64();
+        d_.uncheckedReadFixedF64(out);
         return true;
     }
     MOZ_MUST_USE bool readFixedI8x16(I8x16* out) {
         if (Validate)
             return d_.readFixedI8x16(out);
         d_.uncheckedReadFixedI8x16(out);
         return true;
     }
@@ -570,18 +570,18 @@ class MOZ_STACK_CLASS OpIter : private P
     MOZ_MUST_USE bool readGetLocal(const ValTypeVector& locals, uint32_t* id);
     MOZ_MUST_USE bool readSetLocal(const ValTypeVector& locals, uint32_t* id, Value* value);
     MOZ_MUST_USE bool readTeeLocal(const ValTypeVector& locals, uint32_t* id, Value* value);
     MOZ_MUST_USE bool readGetGlobal(const GlobalDescVector& globals, uint32_t* id);
     MOZ_MUST_USE bool readSetGlobal(const GlobalDescVector& globals, uint32_t* id, Value* value);
     MOZ_MUST_USE bool readTeeGlobal(const GlobalDescVector& globals, uint32_t* id, Value* value);
     MOZ_MUST_USE bool readI32Const(int32_t* i32);
     MOZ_MUST_USE bool readI64Const(int64_t* i64);
-    MOZ_MUST_USE bool readF32Const(RawF32* f32);
-    MOZ_MUST_USE bool readF64Const(RawF64* f64);
+    MOZ_MUST_USE bool readF32Const(float* f32);
+    MOZ_MUST_USE bool readF64Const(double* f64);
     MOZ_MUST_USE bool readI8x16Const(I8x16* i8x16);
     MOZ_MUST_USE bool readI16x8Const(I16x8* i16x8);
     MOZ_MUST_USE bool readI32x4Const(I32x4* i32x4);
     MOZ_MUST_USE bool readF32x4Const(F32x4* f32x4);
     MOZ_MUST_USE bool readB8x16Const(I8x16* i8x16);
     MOZ_MUST_USE bool readB16x8Const(I16x8* i16x8);
     MOZ_MUST_USE bool readB32x4Const(I32x4* i32x4);
     MOZ_MUST_USE bool readCall(uint32_t* calleeIndex);
@@ -1613,37 +1613,37 @@ OpIter<Policy>::readI64Const(int64_t* i6
     if (!push(ValType::I64))
         return false;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-OpIter<Policy>::readF32Const(RawF32* f32)
+OpIter<Policy>::readF32Const(float* f32)
 {
     MOZ_ASSERT(Classify(op_) == OpKind::F32);
 
-    RawF32 unused;
+    float unused;
     if (!readFixedF32(Output ? f32 : &unused))
         return false;
 
     if (!push(ValType::F32))
         return false;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-OpIter<Policy>::readF64Const(RawF64* f64)
+OpIter<Policy>::readF64Const(double* f64)
 {
     MOZ_ASSERT(Classify(op_) == OpKind::F64);
 
-    RawF64 unused;
+    double unused;
     if (!readFixedF64(Output ? f64 : &unused))
        return false;
 
     if (!push(ValType::F64))
         return false;
 
     return true;
 }
--- a/js/src/wasm/WasmBinaryToAST.cpp
+++ b/js/src/wasm/WasmBinaryToAST.cpp
@@ -1039,26 +1039,26 @@ AstDecodeExpr(AstDecodeContext& c)
         int64_t i64;
         if (!c.iter().readI64Const(&i64))
             return false;
         tmp = new(c.lifo) AstConst(Val((uint64_t)i64));
         if (!tmp || !c.push(AstDecodeStackItem(tmp)))
             return false;
         break;
       case uint16_t(Op::F32Const): {
-        RawF32 f32;
+        float f32;
         if (!c.iter().readF32Const(&f32))
             return false;
         tmp = new(c.lifo) AstConst(Val(f32));
         if (!tmp || !c.push(AstDecodeStackItem(tmp)))
             return false;
         break;
       }
       case uint16_t(Op::F64Const): {
-        RawF64 f64;
+        double f64;
         if (!c.iter().readF64Const(&f64))
             return false;
         tmp = new(c.lifo) AstConst(Val(f64));
         if (!tmp || !c.push(AstDecodeStackItem(tmp)))
             return false;
         break;
       }
       case uint16_t(Op::GetLocal):
--- a/js/src/wasm/WasmBinaryToExperimentalText.cpp
+++ b/js/src/wasm/WasmBinaryToExperimentalText.cpp
@@ -159,23 +159,22 @@ PrintInt64(WasmPrintContext& c, int64_t 
         n -= (n / pow) * pow;
         pow /= 10;
     }
 
     return true;
 }
 
 static bool
-PrintDouble(WasmPrintContext& c, RawF64 num)
+PrintDouble(WasmPrintContext& c, double d)
 {
-    double d = num.fp();
     if (IsNegativeZero(d))
         return c.buffer.append("-0.0");
     if (IsNaN(d))
-        return RenderNaN(c.sb(), num);
+        return RenderNaN(c.sb(), d);
     if (IsInfinite(d)) {
         if (d > 0)
             return c.buffer.append("infinity");
         return c.buffer.append("-infinity");
     }
 
     uint32_t startLength = c.buffer.length();
     if (!NumberValueToStringBuffer(c.cx, DoubleValue(d), c.buffer.stringBuffer()))
@@ -187,22 +186,21 @@ PrintDouble(WasmPrintContext& c, RawF64 
         char16_t ch = c.buffer.getChar(i);
         if (ch == '.' || ch == 'e')
             return true;
     }
     return c.buffer.append(".0");
 }
 
 static bool
-PrintFloat32(WasmPrintContext& c, RawF32 num)
+PrintFloat32(WasmPrintContext& c, float f)
 {
-    float f = num.fp();
     if (IsNaN(f))
-        return RenderNaN(c.sb(), num) && c.buffer.append(".f");
-    return PrintDouble(c, RawF64(double(f))) &&
+        return RenderNaN(c.sb(), f) && c.buffer.append(".f");
+    return PrintDouble(c, double(f)) &&
            c.buffer.append("f");
 }
 
 static bool
 PrintEscapedString(WasmPrintContext& c, const AstName& s)
 {
     size_t length = s.length();
     const char16_t* p = s.begin();
--- a/js/src/wasm/WasmBinaryToText.cpp
+++ b/js/src/wasm/WasmBinaryToText.cpp
@@ -96,38 +96,36 @@ RenderInt64(WasmRenderContext& c, int64_
     if (num < 0 && !c.buffer.append("-"))
         return false;
     if (!num)
         return c.buffer.append("0");
     return RenderInBase<10>(c.sb(), mozilla::Abs(num));
 }
 
 static bool
-RenderDouble(WasmRenderContext& c, RawF64 num)
+RenderDouble(WasmRenderContext& c, double d)
 {
-    double d = num.fp();
     if (IsNaN(d))
-        return RenderNaN(c.sb(), num);
+        return RenderNaN(c.sb(), d);
     if (IsNegativeZero(d))
         return c.buffer.append("-0");
     if (IsInfinite(d)) {
         if (d > 0)
             return c.buffer.append("infinity");
         return c.buffer.append("-infinity");
     }
     return NumberValueToStringBuffer(c.cx, DoubleValue(d), c.sb());
 }
 
 static bool
-RenderFloat32(WasmRenderContext& c, RawF32 num)
+RenderFloat32(WasmRenderContext& c, float f)
 {
-    float f = num.fp();
     if (IsNaN(f))
-        return RenderNaN(c.sb(), num);
-    return RenderDouble(c, RawF64(double(f)));
+        return RenderNaN(c.sb(), f);
+    return RenderDouble(c, double(f));
 }
 
 static bool
 RenderEscapedString(WasmRenderContext& c, const AstName& s)
 {
     size_t length = s.length();
     const char16_t* p = s.begin();
     for (size_t i = 0; i < length; i++) {
--- a/js/src/wasm/WasmIonCompile.cpp
+++ b/js/src/wasm/WasmIonCompile.cpp
@@ -338,43 +338,43 @@ class FunctionCompiler
     {
         if (inDeadCode())
             return nullptr;
         MConstant* constant = MConstant::New(alloc(), v, type);
         curBlock_->add(constant);
         return constant;
     }
 
+    MDefinition* constant(float f)
+    {
+        if (inDeadCode())
+            return nullptr;
+        MConstant* constant = MConstant::NewRawFloat32(alloc(), f);
+        curBlock_->add(constant);
+        return constant;
+    }
+
+    MDefinition* constant(double d)
+    {
+        if (inDeadCode())
+            return nullptr;
+        MConstant* constant = MConstant::NewRawDouble(alloc(), d);
+        curBlock_->add(constant);
+        return constant;
+    }
+
     MDefinition* constant(int64_t i)
     {
         if (inDeadCode())
             return nullptr;
         MConstant* constant = MConstant::NewInt64(alloc(), i);
         curBlock_->add(constant);
         return constant;
     }
 
-    MDefinition* constant(RawF32 f)
-    {
-        if (inDeadCode())
-            return nullptr;
-        MConstant* constant = MConstant::New(alloc(), f);
-        curBlock_->add(constant);
-        return constant;
-    }
-
-    MDefinition* constant(RawF64 d)
-    {
-        if (inDeadCode())
-            return nullptr;
-        MConstant* constant = MConstant::New(alloc(), d);
-        curBlock_->add(constant);
-        return constant;
-    }
-
     template <class T>
     MDefinition* unary(MDefinition* op)
     {
         if (inDeadCode())
             return nullptr;
         T* ins = T::New(alloc(), op);
         curBlock_->add(ins);
         return ins;
@@ -3329,17 +3329,17 @@ EmitExpr(FunctionCompiler& f)
         return EmitTeeStore(f, ValType::I64, Scalar::Int32);
       case Op::I64Store:
         return EmitStore(f, ValType::I64, Scalar::Int64);
       case Op::I64TeeStore:
         return EmitTeeStore(f, ValType::I64, Scalar::Int64);
 
       // F32
       case Op::F32Const: {
-        RawF32 f32;
+        float f32;
         if (!f.iter().readF32Const(&f32))
             return false;
 
         f.iter().setResult(f.constant(f32));
         return true;
       }
       case Op::F32Add:
         return EmitAdd(f, ValType::F32, MIRType::Float32);
@@ -3387,17 +3387,17 @@ EmitExpr(FunctionCompiler& f)
         return EmitStore(f, ValType::F32, Scalar::Float32);
       case Op::F32TeeStore:
         return EmitTeeStore(f, ValType::F32, Scalar::Float32);
       case Op::F32TeeStoreF64:
         return EmitTeeStoreWithCoercion(f, ValType::F32, Scalar::Float64);
 
       // F64
       case Op::F64Const: {
-        RawF64 f64;
+        double f64;
         if (!f.iter().readF64Const(&f64))
             return false;
 
         f.iter().setResult(f.constant(f64));
         return true;
       }
       case Op::F64Add:
         return EmitAdd(f, ValType::F64, MIRType::Double);
--- a/js/src/wasm/WasmJS.cpp
+++ b/js/src/wasm/WasmJS.cpp
@@ -36,16 +36,18 @@
 
 #include "jsobjinlines.h"
 
 #include "vm/NativeObject-inl.h"
 
 using namespace js;
 using namespace js::jit;
 using namespace js::wasm;
+
+using mozilla::BitwiseCast;
 using mozilla::CheckedInt;
 using mozilla::IsNaN;
 using mozilla::IsSame;
 using mozilla::Nothing;
 using mozilla::RangedPtr;
 
 bool
 wasm::HasCompilerSupport(ExclusiveContext* cx)
@@ -299,41 +301,45 @@ GetImports(JSContext* cx,
                 val = Val(uint64_t(i64));
                 break;
               }
               case ValType::F32: {
                 if (JitOptions.wasmTestMode && v.isObject()) {
                     uint32_t bits;
                     if (!ReadCustomFloat32NaNObject(cx, v, &bits))
                         return false;
-                    val = Val(RawF32::fromBits(bits));
+                    float f;
+                    BitwiseCast(bits, &f);
+                    val = Val(f);
                     break;
                 }
                 if (!v.isNumber())
                     return ThrowBadImportType(cx, import.field.get(), "Number");
                 double d;
                 if (!ToNumber(cx, v, &d))
                     return false;
-                val = Val(RawF32(float(d)));
+                val = Val(float(d));
                 break;
               }
               case ValType::F64: {
                 if (JitOptions.wasmTestMode && v.isObject()) {
                     uint64_t bits;
                     if (!ReadCustomDoubleNaNObject(cx, v, &bits))
                         return false;
-                    val = Val(RawF64::fromBits(bits));
+                    double d;
+                    BitwiseCast(bits, &d);
+                    val = Val(d);
                     break;
                 }
                 if (!v.isNumber())
                     return ThrowBadImportType(cx, import.field.get(), "Number");
                 double d;
                 if (!ToNumber(cx, v, &d))
                     return false;
-                val = Val(RawF64(d));
+                val = Val(d);
                 break;
               }
               default: {
                 MOZ_CRASH("unexpected import value type");
               }
             }
             if (!globalImports->append(val))
                 return false;
--- a/js/src/wasm/WasmModule.cpp
+++ b/js/src/wasm/WasmModule.cpp
@@ -761,33 +761,31 @@ GetGlobalExport(JSContext* cx, const Glo
         MOZ_ASSERT(JitOptions.wasmTestMode, "no int64 in asm.js/wasm");
         RootedObject obj(cx, CreateI64Object(cx, val.i64()));
         if (!obj)
             return false;
         jsval.set(ObjectValue(*obj));
         return true;
       }
       case ValType::F32: {
-        float f = val.f32().fp();
+        float f = val.f32();
         if (JitOptions.wasmTestMode && IsNaN(f)) {
-            uint32_t bits = val.f32().bits();
-            RootedObject obj(cx, CreateCustomNaNObject(cx, (float*)&bits));
+            RootedObject obj(cx, CreateCustomNaNObject(cx, &f));
             if (!obj)
                 return false;
             jsval.set(ObjectValue(*obj));
             return true;
         }
         jsval.set(DoubleValue(double(f)));
         return true;
       }
       case ValType::F64: {
-        double d = val.f64().fp();
+        double d = val.f64();
         if (JitOptions.wasmTestMode && IsNaN(d)) {
-            uint64_t bits = val.f64().bits();
-            RootedObject obj(cx, CreateCustomNaNObject(cx, (double*)&bits));
+            RootedObject obj(cx, CreateCustomNaNObject(cx, &d));
             if (!obj)
                 return false;
             jsval.set(ObjectValue(*obj));
             return true;
         }
         jsval.set(DoubleValue(d));
         return true;
       }
--- a/js/src/wasm/WasmTextToBinary.cpp
+++ b/js/src/wasm/WasmTextToBinary.cpp
@@ -1775,17 +1775,20 @@ ParseNaNLiteral(WasmParseContext& c, Was
         if (value == 0)
             goto error;
     } else {
         // Produce the spec's default NaN.
         value = (Traits::kSignificandBits + 1) >> 1;
     }
 
     value = (isNegated ? Traits::kSignBit : 0) | Traits::kExponentBits | value;
-    return new (c.lifo) AstConst(Val(Raw<Float>::fromBits(value)));
+
+    Float flt;
+    BitwiseCast(value, &flt);
+    return new (c.lifo) AstConst(Val(flt));
 
   error:
     c.ts.generateError(token, c.error);
     return nullptr;
 }
 
 template <typename Float>
 static bool
@@ -1927,17 +1930,17 @@ ParseFloatLiteral(WasmParseContext& c, W
       case WasmToken::UnsignedInteger: result = token.uint(); break;
       case WasmToken::SignedInteger:   result = token.sint(); break;
       case WasmToken::NegativeZero:    result = -0.; break;
       case WasmToken::Float:           break;
       default:                         c.ts.generateError(token, c.error); return nullptr;
     }
 
     if (token.kind() != WasmToken::Float)
-        return new (c.lifo) AstConst(Val(Raw<Float>(result)));
+        return new (c.lifo) AstConst(Val(Float(result)));
 
     const char16_t* begin = token.begin();
     const char16_t* end = token.end();
     const char16_t* cur = begin;
 
     bool isNegated = false;
     if (*cur == '-' || *cur == '+')
         isNegated = *cur++ == '-';
@@ -1978,17 +1981,17 @@ ParseFloatLiteral(WasmParseContext& c, W
         c.lifo.release(mark);
         break;
       }
     }
 
     if (isNegated)
         result = -result;
 
-    return new (c.lifo) AstConst(Val(Raw<Float>(result)));
+    return new (c.lifo) AstConst(Val(Float(result)));
 }
 
 static AstConst*
 ParseConst(WasmParseContext& c, WasmToken constToken)
 {
     WasmToken val = c.ts.get();
     switch (constToken.valueType()) {
       case ValType::I32: {
--- a/js/src/wasm/WasmTextUtils.cpp
+++ b/js/src/wasm/WasmTextUtils.cpp
@@ -49,30 +49,32 @@ wasm::RenderInBase(StringBuffer& sb, uin
 
     return true;
 }
 
 template bool wasm::RenderInBase<10>(StringBuffer& sb, uint64_t num);
 
 template<class T>
 bool
-wasm::RenderNaN(StringBuffer& sb, Raw<T> num)
+wasm::RenderNaN(StringBuffer& sb, T num)
 {
     typedef typename mozilla::SelectTrait<T> Traits;
+    typedef typename Traits::Bits Bits;
 
-    MOZ_ASSERT(IsNaN(num.fp()));
+    MOZ_ASSERT(IsNaN(num));
 
-    if ((num.bits() & Traits::kSignBit) && !sb.append("-"))
+    Bits bits = mozilla::BitwiseCast<Bits>(num);
+    if ((bits & Traits::kSignBit) && !sb.append("-"))
         return false;
     if (!sb.append("nan"))
         return false;
 
-    typename Traits::Bits payload = num.bits() & Traits::kSignificandBits;
+    Bits payload = bits & Traits::kSignificandBits;
     // Only render the payload if it's not the spec's default NaN.
     if (payload == ((Traits::kSignificandBits + 1) >> 1))
         return true;
 
     return sb.append(":0x") &&
            RenderInBase<16>(sb, payload);
 }
 
-template MOZ_MUST_USE bool wasm::RenderNaN(StringBuffer& b, Raw<float> num);
-template MOZ_MUST_USE bool wasm::RenderNaN(StringBuffer& b, Raw<double> num);
+template MOZ_MUST_USE bool wasm::RenderNaN(StringBuffer& b, float num);
+template MOZ_MUST_USE bool wasm::RenderNaN(StringBuffer& b, double num);
--- a/js/src/wasm/WasmTextUtils.h
+++ b/js/src/wasm/WasmTextUtils.h
@@ -26,21 +26,18 @@
 namespace js {
 namespace wasm {
 
 template<size_t base>
 MOZ_MUST_USE bool
 RenderInBase(StringBuffer& sb, uint64_t num);
 
 template<class T>
-class Raw;
-
-template<class T>
 MOZ_MUST_USE bool
-RenderNaN(StringBuffer& sb, Raw<T> num);
+RenderNaN(StringBuffer& sb, T num);
 
 // Helper class, StringBuffer wrapper, to track the position (line and column)
 // within the generated source.
 
 class WasmPrintBuffer
 {
     StringBuffer& stringBuffer_;
     uint32_t lineno_;
--- a/js/src/wasm/WasmTypes.h
+++ b/js/src/wasm/WasmTypes.h
@@ -332,83 +332,46 @@ ToCString(ExprType type)
 }
 
 static inline const char*
 ToCString(ValType type)
 {
     return ToCString(ToExprType(type));
 }
 
-// Because WebAssembly allows one to define the payload of a NaN value,
-// including the signal/quiet bit (highest order bit of payload), another
-// represenation of floating-point values is required: on some platforms (x86
-// without SSE2), passing a floating-point argument to a function call may use
-// the x87 stack, which has the side-effect of clearing the signal/quiet bit.
-// Because the signal/quiet bit must be preserved (by spec), we use the raw
-// punned integer representation of floating points instead, in function calls.
-//
-// When we leave the WebAssembly sandbox back to JS, NaNs are canonicalized, so
-// this isn't observable from JS.
-
-template<class T>
-class Raw
-{
-    typedef typename mozilla::FloatingPoint<T>::Bits Bits;
-    Bits value_;
-
-  public:
-    Raw() : value_(0) {}
-
-    explicit Raw(T value)
-      : value_(mozilla::BitwiseCast<Bits>(value))
-    {}
-
-    template<class U> MOZ_IMPLICIT Raw(U) = delete;
-
-    static Raw fromBits(Bits bits) { Raw r; r.value_ = bits; return r; }
-
-    Bits bits() const { return value_; }
-    T fp() const { return mozilla::BitwiseCast<T>(value_); }
-};
-
-using RawF64 = Raw<double>;
-using RawF32 = Raw<float>;
-
 // The Val class represents a single WebAssembly value of a given value type,
 // mostly for the purpose of numeric literals and initializers. A Val does not
 // directly map to a JS value since there is not (currently) a precise
 // representation of i64 values. A Val may contain non-canonical NaNs since,
 // within WebAssembly, floats are not canonicalized. Canonicalization must
 // happen at the JS boundary.
 
 class Val
 {
     ValType type_;
     union U {
         uint32_t i32_;
         uint64_t i64_;
-        RawF32 f32_;
-        RawF64 f64_;
+        float f32_;
+        double f64_;
         I8x16 i8x16_;
         I16x8 i16x8_;
         I32x4 i32x4_;
         F32x4 f32x4_;
         U() {}
     } u;
 
   public:
     Val() = default;
 
     explicit Val(uint32_t i32) : type_(ValType::I32) { u.i32_ = i32; }
     explicit Val(uint64_t i64) : type_(ValType::I64) { u.i64_ = i64; }
 
-    explicit Val(RawF32 f32) : type_(ValType::F32) { u.f32_ = f32; }
-    explicit Val(RawF64 f64) : type_(ValType::F64) { u.f64_ = f64; }
-    MOZ_IMPLICIT Val(float) = delete;
-    MOZ_IMPLICIT Val(double) = delete;
+    explicit Val(float f32) : type_(ValType::F32) { u.f32_ = f32; }
+    explicit Val(double f64) : type_(ValType::F64) { u.f64_ = f64; }
 
     explicit Val(const I8x16& i8x16, ValType type = ValType::I8x16) : type_(type) {
         MOZ_ASSERT(type_ == ValType::I8x16 || type_ == ValType::B8x16);
         memcpy(u.i8x16_, i8x16, sizeof(u.i8x16_));
     }
     explicit Val(const I16x8& i16x8, ValType type = ValType::I16x8) : type_(type) {
         MOZ_ASSERT(type_ == ValType::I16x8 || type_ == ValType::B16x8);
         memcpy(u.i16x8_, i16x8, sizeof(u.i16x8_));
@@ -421,18 +384,18 @@ class Val
         memcpy(u.f32x4_, f32x4, sizeof(u.f32x4_));
     }
 
     ValType type() const { return type_; }
     bool isSimd() const { return IsSimdType(type()); }
 
     uint32_t i32() const { MOZ_ASSERT(type_ == ValType::I32); return u.i32_; }
     uint64_t i64() const { MOZ_ASSERT(type_ == ValType::I64); return u.i64_; }
-    RawF32 f32() const { MOZ_ASSERT(type_ == ValType::F32); return u.f32_; }
-    RawF64 f64() const { MOZ_ASSERT(type_ == ValType::F64); return u.f64_; }
+    const float& f32() const { MOZ_ASSERT(type_ == ValType::F32); return u.f32_; }
+    const double& f64() const { MOZ_ASSERT(type_ == ValType::F64); return u.f64_; }
 
     const I8x16& i8x16() const {
         MOZ_ASSERT(type_ == ValType::I8x16 || type_ == ValType::B8x16);
         return u.i8x16_;
     }
     const I16x8& i16x8() const {
         MOZ_ASSERT(type_ == ValType::I16x8 || type_ == ValType::B16x8);
         return u.i16x8_;
--- a/js/src/wasm/WasmValidate.cpp
+++ b/js/src/wasm/WasmValidate.cpp
@@ -1134,24 +1134,24 @@ DecodeInitializerExpression(Decoder& d, 
       case uint16_t(Op::I64Const): {
         int64_t i64;
         if (!d.readVarS64(&i64))
             return d.fail("failed to read initializer i64 expression");
         *init = InitExpr(Val(uint64_t(i64)));
         break;
       }
       case uint16_t(Op::F32Const): {
-        RawF32 f32;
+        float f32;
         if (!d.readFixedF32(&f32))
             return d.fail("failed to read initializer f32 expression");
         *init = InitExpr(Val(f32));
         break;
       }
       case uint16_t(Op::F64Const): {
-        RawF64 f64;
+        double f64;
         if (!d.readFixedF64(&f64))
             return d.fail("failed to read initializer f64 expression");
         *init = InitExpr(Val(f64));
         break;
       }
       case uint16_t(Op::GetGlobal): {
         uint32_t i;
         if (!d.readVarU32(&i))
--- a/js/src/wasm/WasmValidate.h
+++ b/js/src/wasm/WasmValidate.h
@@ -193,21 +193,21 @@ class Encoder
         return writeFixedU8(i);
     }
     MOZ_MUST_USE bool writeFixedU8(uint8_t i) {
         return write<uint8_t>(i);
     }
     MOZ_MUST_USE bool writeFixedU32(uint32_t i) {
         return write<uint32_t>(i);
     }
-    MOZ_MUST_USE bool writeFixedF32(RawF32 f) {
-        return write<uint32_t>(f.bits());
+    MOZ_MUST_USE bool writeFixedF32(float f) {
+        return write<float>(f);
     }
-    MOZ_MUST_USE bool writeFixedF64(RawF64 d) {
-        return write<uint64_t>(d.bits());
+    MOZ_MUST_USE bool writeFixedF64(double d) {
+        return write<double>(d);
     }
     MOZ_MUST_USE bool writeFixedI8x16(const I8x16& i8x16) {
         return write<I8x16>(i8x16);
     }
     MOZ_MUST_USE bool writeFixedI16x8(const I16x8& i16x8) {
         return write<I16x8>(i16x8);
     }
     MOZ_MUST_USE bool writeFixedI32x4(const I32x4& i32x4) {
@@ -432,29 +432,21 @@ class Decoder
     // attempting to align).
 
     MOZ_MUST_USE bool readFixedU8(uint8_t* i) {
         return read<uint8_t>(i);
     }
     MOZ_MUST_USE bool readFixedU32(uint32_t* u) {
         return read<uint32_t>(u);
     }
-    MOZ_MUST_USE bool readFixedF32(RawF32* f) {
-        uint32_t u;
-        if (!read<uint32_t>(&u))
-            return false;
-        *f = RawF32::fromBits(u);
-        return true;
+    MOZ_MUST_USE bool readFixedF32(float* f) {
+        return read<float>(f);
     }
-    MOZ_MUST_USE bool readFixedF64(RawF64* d) {
-        uint64_t u;
-        if (!read<uint64_t>(&u))
-            return false;
-        *d = RawF64::fromBits(u);
-        return true;
+    MOZ_MUST_USE bool readFixedF64(double* d) {
+        return read<double>(d);
     }
     MOZ_MUST_USE bool readFixedI8x16(I8x16* i8x16) {
         return read<I8x16>(i8x16);
     }
     MOZ_MUST_USE bool readFixedI16x8(I16x8* i16x8) {
         return read<I16x8>(i16x8);
     }
     MOZ_MUST_USE bool readFixedI32x4(I32x4* i32x4) {
@@ -551,21 +543,21 @@ class Decoder
     // validation).
 
     uint8_t uncheckedReadFixedU8() {
         return uncheckedRead<uint8_t>();
     }
     uint32_t uncheckedReadFixedU32() {
         return uncheckedRead<uint32_t>();
     }
-    RawF32 uncheckedReadFixedF32() {
-        return RawF32::fromBits(uncheckedRead<uint32_t>());
+    void uncheckedReadFixedF32(float* out) {
+        uncheckedRead<float>(out);
     }
-    RawF64 uncheckedReadFixedF64() {
-        return RawF64::fromBits(uncheckedRead<uint64_t>());
+    void uncheckedReadFixedF64(double* out) {
+        uncheckedRead<double>(out);
     }
     template <typename UInt>
     UInt uncheckedReadVarU() {
         static const unsigned numBits = sizeof(UInt) * CHAR_BIT;
         static const unsigned remainderBits = numBits % 7;
         static const unsigned numBitsInSevens = numBits - remainderBits;
         UInt decoded = 0;
         uint32_t shift = 0;