From 145f71713c4b1931f7e8023be92c9532eed51e62 Mon Sep 17 00:00:00 2001 From: Tooru Fujisawa Date: Tue, 2 Jun 2015 17:28:32 +0900 Subject: [PATCH] Bug 774364 - Part 1: Inline Math.random() in Ion on x86_64. r=sstangl --- js/src/builtin/TestingFunctions.cpp | 4 - js/src/jit/CodeGenerator.cpp | 15 --- js/src/jit/CodeGenerator.h | 1 - js/src/jit/LIR-Common.h | 17 --- js/src/jit/Lowering.cpp | 7 - js/src/jit/Lowering.h | 1 - js/src/jit/arm/CodeGenerator-arm.cpp | 16 +++ js/src/jit/arm/CodeGenerator-arm.h | 2 + js/src/jit/arm/LIR-arm.h | 17 +++ js/src/jit/arm/Lowering-arm.cpp | 7 + js/src/jit/arm/Lowering-arm.h | 1 + js/src/jit/mips/CodeGenerator-mips.cpp | 16 +++ js/src/jit/mips/CodeGenerator-mips.h | 2 + js/src/jit/mips/LIR-mips.h | 17 +++ js/src/jit/mips/Lowering-mips.cpp | 7 + js/src/jit/mips/Lowering-mips.h | 1 + js/src/jit/x64/Assembler-x64.h | 7 + js/src/jit/x64/CodeGenerator-x64.cpp | 126 ++++++++++++++++++ js/src/jit/x64/CodeGenerator-x64.h | 4 + js/src/jit/x64/LIR-x64.h | 35 +++++ js/src/jit/x64/Lowering-x64.cpp | 11 ++ js/src/jit/x64/Lowering-x64.h | 1 + .../jit/x86-shared/BaseAssembler-x86-shared.h | 15 +++ js/src/jit/x86/CodeGenerator-x86.cpp | 16 +++ js/src/jit/x86/CodeGenerator-x86.h | 2 + js/src/jit/x86/LIR-x86.h | 17 +++ js/src/jit/x86/Lowering-x86.cpp | 7 + js/src/jit/x86/Lowering-x86.h | 1 + js/src/jscntxt.h | 3 + js/src/jscompartment.h | 4 + js/src/jsmath.cpp | 8 +- js/src/jsmath.h | 9 +- 32 files changed, 345 insertions(+), 52 deletions(-) diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 1b46612175a..49cff22024c 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -843,10 +843,6 @@ HasChild(JSContext* cx, unsigned argc, jsval* vp) return true; } -// Stolen from jsmath.cpp -static const uint64_t RNG_MULTIPLIER = 0x5DEECE66DLL; -static const uint64_t RNG_MASK = (1LL << 48) - 1; - static bool SetSavedStacksRNGState(JSContext* cx, unsigned argc, jsval* vp) { diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index a5ea2b5933b..95c8ed8a060 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -5155,21 +5155,6 @@ CodeGenerator::visitPowD(LPowD* ins) MOZ_ASSERT(ToFloatRegister(ins->output()) == ReturnDoubleReg); } -void -CodeGenerator::visitRandom(LRandom* ins) -{ - Register temp = ToRegister(ins->temp()); - Register temp2 = ToRegister(ins->temp2()); - - masm.loadJSContext(temp); - - masm.setupUnalignedABICall(1, temp2); - masm.passABIArg(temp); - masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, math_random_no_outparam), MoveOp::DOUBLE); - - MOZ_ASSERT(ToFloatRegister(ins->output()) == ReturnDoubleReg); -} - void CodeGenerator::visitMathFunctionD(LMathFunctionD* ins) { diff --git a/js/src/jit/CodeGenerator.h b/js/src/jit/CodeGenerator.h index 189cc84e895..610022d8edd 100644 --- a/js/src/jit/CodeGenerator.h +++ b/js/src/jit/CodeGenerator.h @@ -215,7 +215,6 @@ class CodeGenerator : public CodeGeneratorSpecific void visitHypot(LHypot* lir); void visitPowI(LPowI* lir); void visitPowD(LPowD* lir); - void visitRandom(LRandom* lir); void visitMathFunctionD(LMathFunctionD* ins); void visitMathFunctionF(LMathFunctionF* ins); void visitModD(LModD* ins); diff --git a/js/src/jit/LIR-Common.h b/js/src/jit/LIR-Common.h index d0ffc6c8033..6823ec0356e 100644 --- a/js/src/jit/LIR-Common.h +++ b/js/src/jit/LIR-Common.h @@ -3126,23 +3126,6 @@ class LPowD : public LCallInstructionHelper<1, 2, 1> } }; -// Math.random(). -class LRandom : public LCallInstructionHelper<1, 0, 2> -{ - public: - LIR_HEADER(Random) - LRandom(const LDefinition& temp, const LDefinition& temp2) { - setTemp(0, temp); - setTemp(1, temp2); - } - const LDefinition* temp() { - return getTemp(0); - } - const LDefinition* temp2() { - return getTemp(1); - } -}; - class LMathFunctionD : public LCallInstructionHelper<1, 1, 1> { public: diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp index f9a860fdcaa..d3823efbea1 100644 --- a/js/src/jit/Lowering.cpp +++ b/js/src/jit/Lowering.cpp @@ -1399,13 +1399,6 @@ LIRGenerator::visitPow(MPow* ins) defineReturn(lir, ins); } -void -LIRGenerator::visitRandom(MRandom* ins) -{ - LRandom* lir = new(alloc()) LRandom(tempFixed(CallTempReg0), tempFixed(CallTempReg1)); - defineReturn(lir, ins); -} - void LIRGenerator::visitMathFunction(MMathFunction* ins) { diff --git a/js/src/jit/Lowering.h b/js/src/jit/Lowering.h index a4fd6a11ddc..249752de76a 100644 --- a/js/src/jit/Lowering.h +++ b/js/src/jit/Lowering.h @@ -130,7 +130,6 @@ class LIRGenerator : public LIRGeneratorSpecific void visitAtan2(MAtan2* ins); void visitHypot(MHypot* ins); void visitPow(MPow* ins); - void visitRandom(MRandom* ins); void visitMathFunction(MMathFunction* ins); void visitAdd(MAdd* ins); void visitSub(MSub* ins); diff --git a/js/src/jit/arm/CodeGenerator-arm.cpp b/js/src/jit/arm/CodeGenerator-arm.cpp index 22924e2f84a..68a2fcadcc7 100644 --- a/js/src/jit/arm/CodeGenerator-arm.cpp +++ b/js/src/jit/arm/CodeGenerator-arm.cpp @@ -10,6 +10,7 @@ #include "jscntxt.h" #include "jscompartment.h" +#include "jsmath.h" #include "jsnum.h" #include "jit/CodeGenerator.h" @@ -2320,3 +2321,18 @@ CodeGeneratorARM::visitMemoryBarrier(LMemoryBarrier* ins) { memoryBarrier(ins->type()); } + +void +CodeGeneratorARM::visitRandom(LRandom* ins) +{ + Register temp = ToRegister(ins->temp()); + Register temp2 = ToRegister(ins->temp2()); + + masm.loadJSContext(temp); + + masm.setupUnalignedABICall(1, temp2); + masm.passABIArg(temp); + masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, math_random_no_outparam), MoveOp::DOUBLE); + + MOZ_ASSERT(ToFloatRegister(ins->output()) == ReturnDoubleReg); +} diff --git a/js/src/jit/arm/CodeGenerator-arm.h b/js/src/jit/arm/CodeGenerator-arm.h index ea5165b01fd..d7a7646a50a 100644 --- a/js/src/jit/arm/CodeGenerator-arm.h +++ b/js/src/jit/arm/CodeGenerator-arm.h @@ -216,6 +216,8 @@ class CodeGeneratorARM : public CodeGeneratorShared void generateInvalidateEpilogue(); + void visitRandom(LRandom* ins); + protected: void visitEffectiveAddress(LEffectiveAddress* ins); void visitUDiv(LUDiv* ins); diff --git a/js/src/jit/arm/LIR-arm.h b/js/src/jit/arm/LIR-arm.h index b47b29ba38c..2589d327ba5 100644 --- a/js/src/jit/arm/LIR-arm.h +++ b/js/src/jit/arm/LIR-arm.h @@ -512,6 +512,23 @@ class LAsmJSAtomicBinopCallout : public LInstructionHelper<1, 2, 0> } }; +// Math.random(). +class LRandom : public LCallInstructionHelper<1, 0, 2> +{ + public: + LIR_HEADER(Random) + LRandom(const LDefinition& temp, const LDefinition& temp2) { + setTemp(0, temp); + setTemp(1, temp2); + } + const LDefinition* temp() { + return getTemp(0); + } + const LDefinition* temp2() { + return getTemp(1); + } +}; + } // namespace jit } // namespace js diff --git a/js/src/jit/arm/Lowering-arm.cpp b/js/src/jit/arm/Lowering-arm.cpp index 8c799ed1771..52abf792b0e 100644 --- a/js/src/jit/arm/Lowering-arm.cpp +++ b/js/src/jit/arm/Lowering-arm.cpp @@ -715,3 +715,10 @@ LIRGeneratorARM::visitSubstr(MSubstr* ins) define(lir, ins); assignSafepoint(lir, ins); } + +void +LIRGeneratorARM::visitRandom(MRandom* ins) +{ + LRandom* lir = new(alloc()) LRandom(tempFixed(CallTempReg0), tempFixed(CallTempReg1)); + defineReturn(lir, ins); +} diff --git a/js/src/jit/arm/Lowering-arm.h b/js/src/jit/arm/Lowering-arm.h index 76472814a1e..b5c23392cbb 100644 --- a/js/src/jit/arm/Lowering-arm.h +++ b/js/src/jit/arm/Lowering-arm.h @@ -105,6 +105,7 @@ class LIRGeneratorARM : public LIRGeneratorShared void visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement* ins); void visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop* ins); void visitSubstr(MSubstr* ins); + void visitRandom(MRandom* ins); }; typedef LIRGeneratorARM LIRGeneratorSpecific; diff --git a/js/src/jit/mips/CodeGenerator-mips.cpp b/js/src/jit/mips/CodeGenerator-mips.cpp index 4844e5ddbcd..b7072773a74 100644 --- a/js/src/jit/mips/CodeGenerator-mips.cpp +++ b/js/src/jit/mips/CodeGenerator-mips.cpp @@ -10,6 +10,7 @@ #include "jscntxt.h" #include "jscompartment.h" +#include "jsmath.h" #include "jsnum.h" #include "jit/CodeGenerator.h" @@ -2152,3 +2153,18 @@ CodeGeneratorMIPS::visitNegF(LNegF* ins) masm.as_negs(output, input); } + +void +CodeGeneratorMIPS::visitRandom(LRandom* ins) +{ + Register temp = ToRegister(ins->temp()); + Register temp2 = ToRegister(ins->temp2()); + + masm.loadJSContext(temp); + + masm.setupUnalignedABICall(1, temp2); + masm.passABIArg(temp); + masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, math_random_no_outparam), MoveOp::DOUBLE); + + MOZ_ASSERT(ToFloatRegister(ins->output()) == ReturnDoubleReg); +} diff --git a/js/src/jit/mips/CodeGenerator-mips.h b/js/src/jit/mips/CodeGenerator-mips.h index 297d2ac4a2f..3e5e1e50c52 100644 --- a/js/src/jit/mips/CodeGenerator-mips.h +++ b/js/src/jit/mips/CodeGenerator-mips.h @@ -245,6 +245,8 @@ class CodeGeneratorMIPS : public CodeGeneratorShared void generateInvalidateEpilogue(); + void visitRandom(LRandom* ins); + protected: void visitEffectiveAddress(LEffectiveAddress* ins); void visitUDivOrMod(LUDivOrMod* ins); diff --git a/js/src/jit/mips/LIR-mips.h b/js/src/jit/mips/LIR-mips.h index 1fe07f5446e..d42583f4428 100644 --- a/js/src/jit/mips/LIR-mips.h +++ b/js/src/jit/mips/LIR-mips.h @@ -387,6 +387,23 @@ class LAsmJSLoadFuncPtr : public LInstructionHelper<1, 1, 0> } }; +// Math.random(). +class LRandom : public LCallInstructionHelper<1, 0, 2> +{ + public: + LIR_HEADER(Random) + LRandom(const LDefinition& temp, const LDefinition& temp2) { + setTemp(0, temp); + setTemp(1, temp2); + } + const LDefinition* temp() { + return getTemp(0); + } + const LDefinition* temp2() { + return getTemp(1); + } +}; + } // namespace jit } // namespace js diff --git a/js/src/jit/mips/Lowering-mips.cpp b/js/src/jit/mips/Lowering-mips.cpp index e780288075f..94d0e0ea744 100644 --- a/js/src/jit/mips/Lowering-mips.cpp +++ b/js/src/jit/mips/Lowering-mips.cpp @@ -584,3 +584,10 @@ LIRGeneratorMIPS::visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBino { MOZ_CRASH("NYI"); } + +void +LIRGeneratorMIPS::visitRandom(MRandom* ins) +{ + LRandom* lir = new(alloc()) LRandom(tempFixed(CallTempReg0), tempFixed(CallTempReg1)); + defineReturn(lir, ins); +} diff --git a/js/src/jit/mips/Lowering-mips.h b/js/src/jit/mips/Lowering-mips.h index 5ac2fc15f04..c8c18163897 100644 --- a/js/src/jit/mips/Lowering-mips.h +++ b/js/src/jit/mips/Lowering-mips.h @@ -105,6 +105,7 @@ class LIRGeneratorMIPS : public LIRGeneratorShared void visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement* ins); void visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop* ins); void visitSubstr(MSubstr* ins); + void visitRandom(MRandom* ins); }; typedef LIRGeneratorMIPS LIRGeneratorSpecific; diff --git a/js/src/jit/x64/Assembler-x64.h b/js/src/jit/x64/Assembler-x64.h index 74cfb3a0e91..d2445140d43 100644 --- a/js/src/jit/x64/Assembler-x64.h +++ b/js/src/jit/x64/Assembler-x64.h @@ -565,6 +565,13 @@ class Assembler : public AssemblerX86Shared masm.xorq_ir(imm.value, dest.encoding()); } + void imulq(Register src, Register dest) { + masm.imulq_rr(src.encoding(), dest.encoding()); + } + void vcvtsi2sdq(Register src, FloatRegister dest) { + masm.vcvtsi2sdq_rr(src.encoding(), dest.encoding()); + } + void mov(ImmWord word, Register dest) { // Use xor for setting registers to zero, as it is specially optimized // for this purpose on modern hardware. Note that it does clobber FLAGS diff --git a/js/src/jit/x64/CodeGenerator-x64.cpp b/js/src/jit/x64/CodeGenerator-x64.cpp index bcecd7778b5..c0fe8b30d18 100644 --- a/js/src/jit/x64/CodeGenerator-x64.cpp +++ b/js/src/jit/x64/CodeGenerator-x64.cpp @@ -819,3 +819,129 @@ CodeGeneratorX64::visitTruncateFToInt32(LTruncateFToInt32* ins) // call a stub if it fails. emitTruncateFloat32(input, output, ins->mir()); } + +namespace js { +namespace jit { + +// Out-of-line math_random_no_outparam call for LRandom. +class OutOfLineRandom : public OutOfLineCodeBase +{ + LRandom* lir_; + + public: + explicit OutOfLineRandom(LRandom* lir) + : lir_(lir) + { } + + void accept(CodeGeneratorX64* codegen) { + codegen->visitOutOfLineRandom(this); + } + + LRandom* lir() const { + return lir_; + } +}; + +} // namespace jit +} // namespace js + +static const double RNG_DSCALE_INV = 1 / RNG_DSCALE; + +void +CodeGeneratorX64::visitRandom(LRandom* ins) +{ + FloatRegister output = ToFloatRegister(ins->output()); + + Register JSCompartmentReg = ToRegister(ins->temp()); + Register rngStateReg = ToRegister(ins->temp2()); + Register highReg = ToRegister(ins->temp3()); + Register lowReg = ToRegister(ins->temp4()); + Register rngMaskReg = ToRegister(ins->temp5()); + + // rngState = cx->compartment()->rngState + masm.loadJSContext(JSCompartmentReg); + masm.loadPtr(Address(JSCompartmentReg, JSContext::offsetOfCompartment()), JSCompartmentReg); + masm.loadPtr(Address(JSCompartmentReg, JSCompartment::offsetOfRngState()), rngStateReg); + + // if rngState == 0, escape from inlined code and call + // math_random_no_outparam. + OutOfLineRandom* ool = new(alloc()) OutOfLineRandom(ins); + addOutOfLineCode(ool, ins->mir()); + masm.branchTestPtr(Assembler::Zero, rngStateReg, rngStateReg, ool->entry()); + + // nextstate = rngState * RNG_MULTIPLIER; + Register& rngMultiplierReg = lowReg; + masm.movq(ImmWord(RNG_MULTIPLIER), rngMultiplierReg); + masm.imulq(rngMultiplierReg, rngStateReg); + + // nextstate += RNG_ADDEND; + masm.addq(Imm32(RNG_ADDEND), rngStateReg); + + // nextstate &= RNG_MASK; + masm.movq(ImmWord(RNG_MASK), rngMaskReg); + masm.andq(rngMaskReg, rngStateReg); + + // rngState = nextstate + + // if rngState == 0, escape from inlined code and call + // math_random_no_outparam. + masm.j(Assembler::Zero, ool->entry()); + + // high = (nextstate >> (RNG_STATE_WIDTH - RNG_HIGH_BITS)) << RNG_LOW_BITS; + masm.movq(rngStateReg, highReg); + masm.shrq(Imm32(RNG_STATE_WIDTH - RNG_HIGH_BITS), highReg); + masm.shlq(Imm32(RNG_LOW_BITS), highReg); + + // nextstate = rngState * RNG_MULTIPLIER; + masm.imulq(rngMultiplierReg, rngStateReg); + + // nextstate += RNG_ADDEND; + masm.addq(Imm32(RNG_ADDEND), rngStateReg); + + // nextstate &= RNG_MASK; + masm.andq(rngMaskReg, rngStateReg); + + // low = nextstate >> (RNG_STATE_WIDTH - RNG_LOW_BITS); + masm.movq(rngStateReg, lowReg); + masm.shrq(Imm32(RNG_STATE_WIDTH - RNG_LOW_BITS), lowReg); + + // output = double(high | low); + masm.orq(highReg, lowReg); + masm.vcvtsi2sdq(lowReg, output); + + // output = output * RNG_DSCALE_INV; + Register& rngDscaleInvReg = lowReg; + masm.movq(ImmPtr(&RNG_DSCALE_INV), rngDscaleInvReg); + masm.vmulsd(Operand(rngDscaleInvReg, 0), output, output); + + // cx->compartment()->rngState = nextstate + masm.storePtr(rngStateReg, Address(JSCompartmentReg, JSCompartment::offsetOfRngState())); + + masm.bind(ool->rejoin()); +} + +void +CodeGeneratorX64::visitOutOfLineRandom(OutOfLineRandom* ool) +{ + LRandom* ins = ool->lir(); + Register temp = ToRegister(ins->temp()); + Register temp2 = ToRegister(ins->temp2()); + MOZ_ASSERT(ToFloatRegister(ins->output()) == ReturnDoubleReg); + + LiveRegisterSet regs; + regs.add(ReturnFloat32Reg); + regs.add(ReturnDoubleReg); + regs.add(ReturnInt32x4Reg); + regs.add(ReturnFloat32x4Reg); + saveVolatile(regs); + + masm.loadJSContext(temp); + + masm.setupUnalignedABICall(1, temp2); + masm.passABIArg(temp); + masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, math_random_no_outparam), MoveOp::DOUBLE); + + restoreVolatile(regs); + + masm.jump(ool->rejoin()); +} diff --git a/js/src/jit/x64/CodeGenerator-x64.h b/js/src/jit/x64/CodeGenerator-x64.h index d9feb995345..218b414726c 100644 --- a/js/src/jit/x64/CodeGenerator-x64.h +++ b/js/src/jit/x64/CodeGenerator-x64.h @@ -12,6 +12,8 @@ namespace js { namespace jit { +class OutOfLineRandom; + class CodeGeneratorX64 : public CodeGeneratorX86Shared { CodeGeneratorX64* thisFromCtor() { @@ -58,6 +60,8 @@ class CodeGeneratorX64 : public CodeGeneratorX86Shared void visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc* ins); void visitAsmJSUInt32ToDouble(LAsmJSUInt32ToDouble* lir); void visitAsmJSUInt32ToFloat32(LAsmJSUInt32ToFloat32* lir); + void visitRandom(LRandom* ins); + void visitOutOfLineRandom(OutOfLineRandom* ool); }; typedef CodeGeneratorX64 CodeGeneratorSpecific; diff --git a/js/src/jit/x64/LIR-x64.h b/js/src/jit/x64/LIR-x64.h index acb3edd4a78..6940b898a1f 100644 --- a/js/src/jit/x64/LIR-x64.h +++ b/js/src/jit/x64/LIR-x64.h @@ -121,6 +121,41 @@ class LAsmJSLoadFuncPtr : public LInstructionHelper<1, 1, 1> } }; +// Math.random(). +class LRandom : public LInstructionHelper<1, 0, 5> +{ + public: + LIR_HEADER(Random) + LRandom(const LDefinition &temp, const LDefinition &temp2, const LDefinition &temp3, + const LDefinition &temp4, const LDefinition &temp5) + { + setTemp(0, temp); + setTemp(1, temp2); + setTemp(2, temp3); + setTemp(3, temp4); + setTemp(4, temp5); + } + const LDefinition* temp() { + return getTemp(0); + } + const LDefinition* temp2() { + return getTemp(1); + } + const LDefinition *temp3() { + return getTemp(2); + } + const LDefinition *temp4() { + return getTemp(3); + } + const LDefinition *temp5() { + return getTemp(4); + } + + MRandom* mir() const { + return mir_->toRandom(); + } +}; + } // namespace jit } // namespace js diff --git a/js/src/jit/x64/Lowering-x64.cpp b/js/src/jit/x64/Lowering-x64.cpp index 1ddc450715f..f857825abe2 100644 --- a/js/src/jit/x64/Lowering-x64.cpp +++ b/js/src/jit/x64/Lowering-x64.cpp @@ -309,3 +309,14 @@ LIRGeneratorX64::visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic { MOZ_CRASH("NYI"); } + +void +LIRGeneratorX64::visitRandom(MRandom* ins) +{ + LRandom *lir = new(alloc()) LRandom(temp(), + temp(), + temp(), + temp(), + temp()); + defineFixed(lir, ins, LFloatReg(ReturnDoubleReg)); +} diff --git a/js/src/jit/x64/Lowering-x64.h b/js/src/jit/x64/Lowering-x64.h index caa00d1bbbf..f0666f76d13 100644 --- a/js/src/jit/x64/Lowering-x64.h +++ b/js/src/jit/x64/Lowering-x64.h @@ -51,6 +51,7 @@ class LIRGeneratorX64 : public LIRGeneratorX86Shared void visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap* ins); void visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic* ins); void visitSubstr(MSubstr* ins); + void visitRandom(MRandom* ins); }; typedef LIRGeneratorX64 LIRGeneratorSpecific; diff --git a/js/src/jit/x86-shared/BaseAssembler-x86-shared.h b/js/src/jit/x86-shared/BaseAssembler-x86-shared.h index 7c7dddb82c5..9b3ce213623 100644 --- a/js/src/jit/x86-shared/BaseAssembler-x86-shared.h +++ b/js/src/jit/x86-shared/BaseAssembler-x86-shared.h @@ -1311,6 +1311,14 @@ public: } } +#ifdef JS_CODEGEN_X64 + void imulq_rr(RegisterID src, RegisterID dst) + { + spew("imulq %s, %s", GPReg64Name(src), GPReg64Name(dst)); + m_formatter.twoByteOp64(OP2_IMUL_GvEv, src, dst); + } +#endif + void idivl_r(RegisterID divisor) { spew("idivl %s", GPReg32Name(divisor)); @@ -2771,6 +2779,13 @@ public: } #endif +#ifdef JS_CODEGEN_X64 + void vcvtsi2sdq_rr(RegisterID src, XMMRegisterID dst) + { + twoByteOpInt64Simd("vcvtsi2sdq", VEX_SD, OP2_CVTSI2SD_VsdEd, src, invalid_xmm, dst); + } +#endif + void vcvttsd2si_rr(XMMRegisterID src, RegisterID dst) { twoByteOpSimdInt32("vcvttsd2si", VEX_SD, OP2_CVTTSD2SI_GdWsd, src, dst); diff --git a/js/src/jit/x86/CodeGenerator-x86.cpp b/js/src/jit/x86/CodeGenerator-x86.cpp index ed5d9683b5e..957e5d97de7 100644 --- a/js/src/jit/x86/CodeGenerator-x86.cpp +++ b/js/src/jit/x86/CodeGenerator-x86.cpp @@ -9,6 +9,7 @@ #include "mozilla/Casting.h" #include "mozilla/DebugOnly.h" +#include "jsmath.h" #include "jsnum.h" #include "jit/IonCaches.h" @@ -1112,3 +1113,18 @@ CodeGeneratorX86::visitOutOfLineTruncateFloat32(OutOfLineTruncateFloat32* ool) masm.jump(ool->rejoin()); } + +void +CodeGeneratorX86::visitRandom(LRandom* ins) +{ + Register temp = ToRegister(ins->temp()); + Register temp2 = ToRegister(ins->temp2()); + + masm.loadJSContext(temp); + + masm.setupUnalignedABICall(1, temp2); + masm.passABIArg(temp); + masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, math_random_no_outparam), MoveOp::DOUBLE); + + MOZ_ASSERT(ToFloatRegister(ins->output()) == ReturnDoubleReg); +} diff --git a/js/src/jit/x86/CodeGenerator-x86.h b/js/src/jit/x86/CodeGenerator-x86.h index 62050079918..08625869e3f 100644 --- a/js/src/jit/x86/CodeGenerator-x86.h +++ b/js/src/jit/x86/CodeGenerator-x86.h @@ -71,6 +71,8 @@ class CodeGeneratorX86 : public CodeGeneratorX86Shared void visitOutOfLineTruncate(OutOfLineTruncate* ool); void visitOutOfLineTruncateFloat32(OutOfLineTruncateFloat32* ool); + void visitRandom(LRandom* ins); + private: void asmJSAtomicComputeAddress(Register addrTemp, Register ptrReg, bool boundsCheck, int32_t offset, int32_t endOffset, Register out, diff --git a/js/src/jit/x86/LIR-x86.h b/js/src/jit/x86/LIR-x86.h index 3e9c931434e..7009fdcfa92 100644 --- a/js/src/jit/x86/LIR-x86.h +++ b/js/src/jit/x86/LIR-x86.h @@ -143,6 +143,23 @@ class LAsmJSLoadFuncPtr : public LInstructionHelper<1, 1, 0> } }; +// Math.random(). +class LRandom : public LCallInstructionHelper<1, 0, 2> +{ + public: + LIR_HEADER(Random) + LRandom(const LDefinition& temp, const LDefinition& temp2) { + setTemp(0, temp); + setTemp(1, temp2); + } + const LDefinition* temp() { + return getTemp(0); + } + const LDefinition* temp2() { + return getTemp(1); + } +}; + } // namespace jit } // namespace js diff --git a/js/src/jit/x86/Lowering-x86.cpp b/js/src/jit/x86/Lowering-x86.cpp index aa791d56292..0205c6a83ce 100644 --- a/js/src/jit/x86/Lowering-x86.cpp +++ b/js/src/jit/x86/Lowering-x86.cpp @@ -413,3 +413,10 @@ LIRGeneratorX86::visitSubstr(MSubstr* ins) define(lir, ins); assignSafepoint(lir, ins); } + +void +LIRGeneratorX86::visitRandom(MRandom* ins) +{ + LRandom* lir = new(alloc()) LRandom(tempFixed(CallTempReg0), tempFixed(CallTempReg1)); + defineReturn(lir, ins); +} diff --git a/js/src/jit/x86/Lowering-x86.h b/js/src/jit/x86/Lowering-x86.h index d73e29c1702..6b552dbf08b 100644 --- a/js/src/jit/x86/Lowering-x86.h +++ b/js/src/jit/x86/Lowering-x86.h @@ -57,6 +57,7 @@ class LIRGeneratorX86 : public LIRGeneratorX86Shared void visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap* ins); void visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic* ins); void visitSubstr(MSubstr* ins); + void visitRandom(MRandom* ins); void lowerPhi(MPhi* phi); static bool allowTypedElementHoleCheck() { diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 68faa7a2d2e..18528a34b83 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -292,6 +292,9 @@ struct JSContext : public js::ExclusiveContext, static size_t offsetOfRuntime() { return offsetof(JSContext, runtime_); } + static size_t offsetOfCompartment() { + return offsetof(JSContext, compartment_); + } friend class js::ExclusiveContext; friend class JS::AutoSaveExceptionState; diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index ae241835744..888361cbaee 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -455,6 +455,10 @@ struct JSCompartment /* Random number generator state, used by jsmath.cpp. */ uint64_t rngState; + static size_t offsetOfRngState() { + return offsetof(JSCompartment, rngState); + } + private: JSCompartment* thisForCtor() { return this; } diff --git a/js/src/jsmath.cpp b/js/src/jsmath.cpp index ab3ecdb4f5c..53303640390 100644 --- a/js/src/jsmath.cpp +++ b/js/src/jsmath.cpp @@ -765,10 +765,6 @@ random_generateSeed() return seed.u64; } -static const uint64_t RNG_MULTIPLIER = 0x5DEECE66DLL; -static const uint64_t RNG_ADDEND = 0xBLL; -static const uint64_t RNG_MASK = (1LL << 48) - 1; - /* * Math.random() support, lifted from java.util.Random.java. */ @@ -785,7 +781,7 @@ uint64_t js::random_next(uint64_t* rngState, int bits) { MOZ_ASSERT((*rngState & 0xffff000000000000ULL) == 0, "Bad rngState"); - MOZ_ASSERT(bits > 0 && bits <= 48, "bits is out of range"); + MOZ_ASSERT(bits > 0 && bits <= RNG_STATE_WIDTH, "bits is out of range"); if (*rngState == 0) { random_initState(rngState); @@ -795,7 +791,7 @@ js::random_next(uint64_t* rngState, int bits) nextstate += RNG_ADDEND; nextstate &= RNG_MASK; *rngState = nextstate; - return nextstate >> (48 - bits); + return nextstate >> (RNG_STATE_WIDTH - bits); } double diff --git a/js/src/jsmath.h b/js/src/jsmath.h index 5f63df56753..90a262af653 100644 --- a/js/src/jsmath.h +++ b/js/src/jsmath.h @@ -97,11 +97,18 @@ extern uint64_t random_next(uint64_t* rngState, int bits); static const double RNG_DSCALE = double(1LL << 53); +static const int RNG_STATE_WIDTH = 48; +static const int RNG_HIGH_BITS = 26; +static const int RNG_LOW_BITS = 27; +static const uint64_t RNG_MULTIPLIER = 0x5DEECE66DLL; +static const uint64_t RNG_ADDEND = 0xBLL; +static const uint64_t RNG_MASK = (1LL << RNG_STATE_WIDTH) - 1; inline double random_nextDouble(uint64_t* rng) { - return double((random_next(rng, 26) << 27) + random_next(rng, 27)) / RNG_DSCALE; + return double((random_next(rng, RNG_HIGH_BITS) << RNG_LOW_BITS) + + random_next(rng, RNG_LOW_BITS)) / RNG_DSCALE; } extern double