mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 774364 - Part 1: Inline Math.random() in Ion on x86_64. r=sstangl
This commit is contained in:
parent
093be883f1
commit
145f71713c
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -216,6 +216,8 @@ class CodeGeneratorARM : public CodeGeneratorShared
|
||||
|
||||
void generateInvalidateEpilogue();
|
||||
|
||||
void visitRandom(LRandom* ins);
|
||||
|
||||
protected:
|
||||
void visitEffectiveAddress(LEffectiveAddress* ins);
|
||||
void visitUDiv(LUDiv* ins);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -245,6 +245,8 @@ class CodeGeneratorMIPS : public CodeGeneratorShared
|
||||
|
||||
void generateInvalidateEpilogue();
|
||||
|
||||
void visitRandom(LRandom* ins);
|
||||
|
||||
protected:
|
||||
void visitEffectiveAddress(LEffectiveAddress* ins);
|
||||
void visitUDivOrMod(LUDivOrMod* ins);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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<CodeGeneratorX64>
|
||||
{
|
||||
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());
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user