diff --git a/js/src/assembler/assembler/X86Assembler.h b/js/src/assembler/assembler/X86Assembler.h index 05a7fa4c9817..751b013008e0 100644 --- a/js/src/assembler/assembler/X86Assembler.h +++ b/js/src/assembler/assembler/X86Assembler.h @@ -2643,6 +2643,14 @@ public: m_formatter.twoByteRipOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, 0); return JmpSrc(m_formatter.size()); } + JmpSrc movss_ripr(XMMRegisterID dst) + { + spew("movss \?(%%rip), %s", + nameFPReg(dst)); + m_formatter.prefix(PRE_SSE_F3); + m_formatter.twoByteRipOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, 0); + return JmpSrc(m_formatter.size()); + } JmpSrc movsd_rrip(XMMRegisterID src) { spew("movsd %s, \?(%%rip)", diff --git a/js/src/jit/x64/MacroAssembler-x64.cpp b/js/src/jit/x64/MacroAssembler-x64.cpp index 09bd3e232446..a4f914dbac72 100644 --- a/js/src/jit/x64/MacroAssembler-x64.cpp +++ b/js/src/jit/x64/MacroAssembler-x64.cpp @@ -48,12 +48,46 @@ MacroAssemblerX64::loadConstantDouble(double d, const FloatRegister &dest) masm.setNextJump(j, prev); } +void +MacroAssemblerX64::loadConstantFloat32(float f, const FloatRegister &dest) +{ + // In particular, use hardware instructions if loading 0 + uint32_t u = mozilla::BitwiseCast(f); + if (u == 0) { + xorps(dest, dest); + return; + } + + if (!floatMap_.initialized()) { + enoughMemory_ &= floatMap_.init(); + if (!enoughMemory_) + return; + } + size_t floatIndex; + if (FloatMap::AddPtr p = floatMap_.lookupForAdd(f)) { + floatIndex = p->value; + } else { + floatIndex = floats_.length(); + enoughMemory_ &= floats_.append(Float(f)); + enoughMemory_ &= floatMap_.add(p, f, floatIndex); + if (!enoughMemory_) + return; + } + Float &flt = floats_[floatIndex]; + JS_ASSERT(!flt.uses.bound()); + + // See comment in loadConstantDouble + JmpSrc j = masm.movss_ripr(dest.code()); + JmpSrc prev = JmpSrc(flt.uses.use(j.offset())); + masm.setNextJump(j, prev); +} + void MacroAssemblerX64::finish() { JS_STATIC_ASSERT(CodeAlignment >= sizeof(double)); - if (!doubles_.empty()) + if (!doubles_.empty() || !floats_.empty()) masm.align(sizeof(double)); for (size_t i = 0; i < doubles_.length(); i++) { @@ -62,6 +96,13 @@ MacroAssemblerX64::finish() masm.doubleConstant(dbl.value); } + // No need to align on sizeof(float) as we are aligned on sizeof(double); + for (size_t i = 0; i < floats_.length(); i++) { + Float &flt = floats_[i]; + bind(&flt.uses); + masm.floatConstant(flt.value); + } + MacroAssemblerX86Shared::finish(); } diff --git a/js/src/jit/x64/MacroAssembler-x64.h b/js/src/jit/x64/MacroAssembler-x64.h index 7e9bf376d806..f21bbf15f6b9 100644 --- a/js/src/jit/x64/MacroAssembler-x64.h +++ b/js/src/jit/x64/MacroAssembler-x64.h @@ -57,6 +57,16 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared typedef HashMap, SystemAllocPolicy> DoubleMap; DoubleMap doubleMap_; + struct Float { + float value; + NonAssertingLabel uses; + Float(float value) : value(value) {} + }; + Vector floats_; + + typedef HashMap, SystemAllocPolicy> FloatMap; + FloatMap floatMap_; + void setupABICall(uint32_t arg); protected: @@ -1010,15 +1020,7 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared } void loadConstantDouble(double d, const FloatRegister &dest); - void loadConstantFloat32(float f, const FloatRegister &dest) { - union FloatPun { - uint32_t u; - float f; - } pun; - pun.f = f; - mov(ImmWord(pun.u), ScratchReg); - movq(ScratchReg, dest); - } + void loadConstantFloat32(float f, const FloatRegister &dest); void branchTruncateDouble(const FloatRegister &src, const Register &dest, Label *fail) { const uint64_t IndefiniteIntegerValue = 0x8000000000000000;