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 <kilvadyb@homejinni.com>. git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16695 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
705d813291
commit
4f09f42866
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user