| Index: src/arm/lithium-codegen-arm.cc
|
| diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
|
| index fcbc90da5f8ed39fe30dee540a5c0e08542579a5..2a707a83fab6b851a1b80400a143fcf7f9d0e5fa 100644
|
| --- a/src/arm/lithium-codegen-arm.cc
|
| +++ b/src/arm/lithium-codegen-arm.cc
|
| @@ -3230,15 +3230,62 @@ void LCodeGen::DoPower(LPower* instr) {
|
|
|
|
|
| void LCodeGen::DoRandom(LRandom* instr) {
|
| + class DeferredDoRandom: public LDeferredCode {
|
| + public:
|
| + DeferredDoRandom(LCodeGen* codegen, LRandom* instr)
|
| + : LDeferredCode(codegen), instr_(instr) { }
|
| + virtual void Generate() { codegen()->DoDeferredRandom(instr_); }
|
| + virtual LInstruction* instr() { return instr_; }
|
| + private:
|
| + LRandom* instr_;
|
| + };
|
| +
|
| + DeferredDoRandom* deferred = new DeferredDoRandom(this, instr);
|
| +
|
| // Having marked this instruction as a call we can use any
|
| // registers.
|
| ASSERT(ToDoubleRegister(instr->result()).is(d7));
|
| ASSERT(ToRegister(instr->InputAt(0)).is(r0));
|
|
|
| - __ PrepareCallCFunction(1, scratch0());
|
| + static const int kSeedSize = sizeof(uint32_t);
|
| + STATIC_ASSERT(kPointerSize == kSeedSize);
|
| +
|
| __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset));
|
| - __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
|
| + static const int kRandomSeedOffset =
|
| + FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize;
|
| + __ ldr(r2, FieldMemOperand(r0, kRandomSeedOffset));
|
| + // r2: FixedArray of the global context's random seeds
|
| +
|
| + // Load state[0].
|
| + __ ldr(r1, FieldMemOperand(r2, ByteArray::kHeaderSize));
|
| + __ cmp(r1, Operand(0));
|
| + __ b(eq, deferred->entry());
|
| + // Load state[1].
|
| + __ ldr(r0, FieldMemOperand(r2, ByteArray::kHeaderSize + kSeedSize));
|
| + // r1: state[0].
|
| + // r0: state[1].
|
| +
|
| + // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16)
|
| + __ and_(r3, r1, Operand(0xFFFF));
|
| + __ mov(r4, Operand(18273));
|
| + __ mul(r3, r3, r4);
|
| + __ add(r1, r3, Operand(r1, LSR, 16));
|
| + // Save state[0].
|
| + __ str(r1, FieldMemOperand(r2, ByteArray::kHeaderSize));
|
| +
|
| + // state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16)
|
| + __ and_(r3, r0, Operand(0xFFFF));
|
| + __ mov(r4, Operand(36969));
|
| + __ mul(r3, r3, r4);
|
| + __ add(r0, r3, Operand(r0, LSR, 16));
|
| + // Save state[1].
|
| + __ str(r0, FieldMemOperand(r2, ByteArray::kHeaderSize + kSeedSize));
|
| +
|
| + // Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF)
|
| + __ and_(r0, r0, Operand(0x3FFFF));
|
| + __ add(r0, r0, Operand(r1, LSL, 14));
|
|
|
| + __ bind(deferred->exit());
|
| // 0x41300000 is the top half of 1.0 x 2^20 as a double.
|
| // Create this constant using mov/orr to avoid PC relative load.
|
| __ mov(r1, Operand(0x41000000));
|
| @@ -3253,6 +3300,13 @@ void LCodeGen::DoRandom(LRandom* instr) {
|
| }
|
|
|
|
|
| +void LCodeGen::DoDeferredRandom(LRandom* instr) {
|
| + __ PrepareCallCFunction(1, scratch0());
|
| + __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
|
| + // Return value is in r0.
|
| +}
|
| +
|
| +
|
| void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
|
| ASSERT(ToDoubleRegister(instr->result()).is(d2));
|
| TranscendentalCacheStub stub(TranscendentalCache::LOG,
|
|
|