From 4f09f428663cde5f5c4624a6016a66c98baf927c Mon Sep 17 00:00:00 2001 From: "palfia@homejinni.com" Date: Thu, 12 Sep 2013 21:17:43 +0000 Subject: [PATCH] MIPS: Improve code generation for the HRandom instruction. Port r16684 (e0f70aa) Original commit message: Since the per-context random number generator is now properly seeded upon context creation, we do not need to check for lazy-initialization anymore, and so we can implement the HRandom instruction w/o having to call into the C function (which means we don't need to MarkAsCall anymore). TEST=cctest/test-random BUG= R=gergely@homejinni.com Review URL: https://codereview.chromium.org/23851028 Patch from Balazs Kilvady . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16695 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/mips/lithium-codegen-mips.cc | 91 +++++++++++++------------------- src/mips/lithium-codegen-mips.h | 1 - src/mips/lithium-mips.cc | 10 ++-- src/mips/lithium-mips.h | 15 ++++-- 4 files changed, 57 insertions(+), 60 deletions(-) diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index ab713a3cec..b37c7e0419 100644 --- a/src/mips/lithium-codegen-mips.cc +++ b/src/mips/lithium-codegen-mips.cc @@ -3813,79 +3813,64 @@ void LCodeGen::DoPower(LPower* instr) { void LCodeGen::DoRandom(LRandom* instr) { - class DeferredDoRandom V8_FINAL : public LDeferredCode { - public: - DeferredDoRandom(LCodeGen* codegen, LRandom* instr) - : LDeferredCode(codegen), instr_(instr) { } - virtual void Generate() V8_OVERRIDE { codegen()->DoDeferredRandom(instr_); } - virtual LInstruction* instr() V8_OVERRIDE { return instr_; } - private: - LRandom* instr_; - }; - - DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr); - // Having marked this instruction as a call we can use any - // registers. - ASSERT(ToDoubleRegister(instr->result()).is(f0)); - ASSERT(ToRegister(instr->global_object()).is(a0)); - + // Assert that the register size is indeed the size of each seed. static const int kSeedSize = sizeof(uint32_t); STATIC_ASSERT(kPointerSize == kSeedSize); - __ lw(a0, FieldMemOperand(a0, GlobalObject::kNativeContextOffset)); + // Load native context. + Register global_object = ToRegister(instr->global_object()); + Register native_context = global_object; + __ lw(native_context, FieldMemOperand( + global_object, GlobalObject::kNativeContextOffset)); + + // Load state (FixedArray of the native context's random seeds). static const int kRandomSeedOffset = FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize; - __ lw(a2, FieldMemOperand(a0, kRandomSeedOffset)); - // a2: FixedArray of the native context's random seeds + Register state = native_context; + __ lw(state, FieldMemOperand(native_context, kRandomSeedOffset)); // Load state[0]. - __ lw(a1, FieldMemOperand(a2, ByteArray::kHeaderSize)); - __ Branch(deferred->entry(), eq, a1, Operand(zero_reg)); + Register state0 = ToRegister(instr->scratch()); + __ lw(state0, FieldMemOperand(state, ByteArray::kHeaderSize)); // Load state[1]. - __ lw(a0, FieldMemOperand(a2, ByteArray::kHeaderSize + kSeedSize)); - // a1: state[0]. - // a0: state[1]. + Register state1 = ToRegister(instr->scratch2()); + __ lw(state1, FieldMemOperand(state, ByteArray::kHeaderSize + kSeedSize)); // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16) - __ And(a3, a1, Operand(0xFFFF)); - __ li(t0, Operand(18273)); - __ Mul(a3, a3, t0); - __ srl(a1, a1, 16); - __ Addu(a1, a3, a1); + Register scratch3 = ToRegister(instr->scratch3()); + Register scratch4 = scratch0(); + __ And(scratch3, state0, Operand(0xFFFF)); + __ li(scratch4, Operand(18273)); + __ Mul(scratch3, scratch3, scratch4); + __ srl(state0, state0, 16); + __ Addu(state0, scratch3, state0); // Save state[0]. - __ sw(a1, FieldMemOperand(a2, ByteArray::kHeaderSize)); + __ sw(state0, FieldMemOperand(state, ByteArray::kHeaderSize)); // state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16) - __ And(a3, a0, Operand(0xFFFF)); - __ li(t0, Operand(36969)); - __ Mul(a3, a3, t0); - __ srl(a0, a0, 16), - __ Addu(a0, a3, a0); + __ And(scratch3, state1, Operand(0xFFFF)); + __ li(scratch4, Operand(36969)); + __ Mul(scratch3, scratch3, scratch4); + __ srl(state1, state1, 16), + __ Addu(state1, scratch3, state1); // Save state[1]. - __ sw(a0, FieldMemOperand(a2, ByteArray::kHeaderSize + kSeedSize)); + __ sw(state1, FieldMemOperand(state, ByteArray::kHeaderSize + kSeedSize)); // Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF) - __ And(a0, a0, Operand(0x3FFFF)); - __ sll(a1, a1, 14); - __ Addu(v0, a0, a1); - - __ bind(deferred->exit()); + Register random = scratch4; + __ And(random, state1, Operand(0x3FFFF)); + __ sll(state0, state0, 14); + __ Addu(random, random, state0); // 0x41300000 is the top half of 1.0 x 2^20 as a double. - __ li(a2, Operand(0x41300000)); + __ li(scratch3, Operand(0x41300000)); // Move 0x41300000xxxxxxxx (x = random bits in v0) to FPU. - __ Move(f12, v0, a2); + DoubleRegister result = ToDoubleRegister(instr->result()); + __ Move(result, random, scratch3); // Move 0x4130000000000000 to FPU. - __ Move(f14, zero_reg, a2); - // Subtract to get the result. - __ sub_d(f0, f12, f14); -} - - -void LCodeGen::DoDeferredRandom(LRandom* instr) { - __ PrepareCallCFunction(1, scratch0()); - __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); - // Return value is in v0. + DoubleRegister scratch5 = double_scratch0(); + __ Move(scratch5, zero_reg, scratch3); + __ sub_d(result, result, scratch5); } diff --git a/src/mips/lithium-codegen-mips.h b/src/mips/lithium-codegen-mips.h index 8437435199..84105cae35 100644 --- a/src/mips/lithium-codegen-mips.h +++ b/src/mips/lithium-codegen-mips.h @@ -147,7 +147,6 @@ class LCodeGen V8_FINAL BASE_EMBEDDED { void DoDeferredTaggedToI(LTaggedToI* instr); void DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr); void DoDeferredStackCheck(LStackCheck* instr); - void DoDeferredRandom(LRandom* instr); void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr); void DoDeferredStringCharFromCode(LStringCharFromCode* instr); void DoDeferredAllocate(LAllocate* instr); diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc index 9476f4def9..4dc80226f2 100644 --- a/src/mips/lithium-mips.cc +++ b/src/mips/lithium-mips.cc @@ -1624,9 +1624,13 @@ LInstruction* LChunkBuilder::DoPower(HPower* instr) { LInstruction* LChunkBuilder::DoRandom(HRandom* instr) { ASSERT(instr->representation().IsDouble()); ASSERT(instr->global_object()->representation().IsTagged()); - LOperand* global_object = UseFixed(instr->global_object(), a0); - LRandom* result = new(zone()) LRandom(global_object); - return MarkAsCall(DefineFixedDouble(result, f0), instr); + LOperand* global_object = UseTempRegister(instr->global_object()); + LOperand* scratch = TempRegister(); + LOperand* scratch2 = TempRegister(); + LOperand* scratch3 = TempRegister(); + LRandom* result = new(zone()) LRandom( + global_object, scratch, scratch2, scratch3); + return DefineFixedDouble(result, f0); } diff --git a/src/mips/lithium-mips.h b/src/mips/lithium-mips.h index fa2aed5afe..29a8eac63f 100644 --- a/src/mips/lithium-mips.h +++ b/src/mips/lithium-mips.h @@ -1444,13 +1444,22 @@ class LPower V8_FINAL : public LTemplateInstruction<1, 2, 0> { }; -class LRandom V8_FINAL : public LTemplateInstruction<1, 1, 0> { +class LRandom V8_FINAL : public LTemplateInstruction<1, 1, 3> { public: - explicit LRandom(LOperand* global_object) { + LRandom(LOperand* global_object, + LOperand* scratch, + LOperand* scratch2, + LOperand* scratch3) { inputs_[0] = global_object; + temps_[0] = scratch; + temps_[1] = scratch2; + temps_[2] = scratch3; } - LOperand* global_object() { return inputs_[0]; } + LOperand* global_object() const { return inputs_[0]; } + LOperand* scratch() const { return temps_[0]; } + LOperand* scratch2() const { return temps_[1]; } + LOperand* scratch3() const { return temps_[2]; } DECLARE_CONCRETE_INSTRUCTION(Random, "random") DECLARE_HYDROGEN_ACCESSOR(Random)