Commit c3c36137 authored by yangguo@chromium.org's avatar yangguo@chromium.org

Port r10939 to x64 and arm (inline Math.random in crankshaft).

BUG=
TEST=

Review URL: https://chromiumcodereview.appspot.com/9615012

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10947 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 5440d43d
......@@ -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,
......
......@@ -114,6 +114,7 @@ class LCodeGen BASE_EMBEDDED {
void DoDeferredTaggedToI(LTaggedToI* instr);
void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr);
void DoDeferredStackCheck(LStackCheck* instr);
void DoDeferredRandom(LRandom* instr);
void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
void DoDeferredAllocateObject(LAllocateObject* instr);
......
......@@ -3081,25 +3081,27 @@ void LCodeGen::DoRandom(LRandom* instr) {
// If state[0] == 0, call runtime to initialize seeds.
__ test(ecx, ecx);
__ j(zero, deferred->entry());
// Load state[1].
__ mov(eax, FieldOperand(ebx, ByteArray::kHeaderSize + kSeedSize));
// ecx: state[0]
// eax: state[1]
// state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16)
__ movzx_w(edx, ecx);
__ imul(edx, edx, 18273);
__ shr(ecx, 16);
__ add(ecx, edx);
// Save state[0].
__ mov(FieldOperand(ebx, ByteArray::kHeaderSize), ecx);
// Load state[1].
// state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16);
__ mov(eax, FieldOperand(ebx, ByteArray::kHeaderSize + kSeedSize));
// state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16)
__ movzx_w(edx, eax);
__ imul(edx, edx, 36969);
__ shr(eax, 16);
__ add(eax, edx);
// Save state[1].
__ mov(FieldOperand(ebx, ByteArray::kHeaderSize + kSeedSize), eax);
// ecx: state[0]
// eax: state[1]
// Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF)
__ shl(ecx, 14);
__ and_(eax, Immediate(0x3FFFF));
......
......@@ -2966,6 +2966,18 @@ 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(xmm1));
......@@ -2980,12 +2992,49 @@ void LCodeGen::DoRandom(LRandom* instr) {
Register global_object = rdi;
#endif
__ PrepareCallCFunction(1);
static const int kSeedSize = sizeof(uint32_t);
STATIC_ASSERT(kPointerSize == 2 * kSeedSize);
__ movq(global_object,
FieldOperand(global_object, GlobalObject::kGlobalContextOffset));
__ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
static const int kRandomSeedOffset =
FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize;
__ movq(rbx, FieldOperand(global_object, kRandomSeedOffset));
// rbx: FixedArray of the global context's random seeds
// Load state[0].
__ movl(rax, FieldOperand(rbx, ByteArray::kHeaderSize));
// If state[0] == 0, call runtime to initialize seeds.
__ testl(rax, rax);
__ j(zero, deferred->entry());
// Load state[1].
__ movl(rcx, FieldOperand(rbx, ByteArray::kHeaderSize + kSeedSize));
// state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16)
// Only operate on the lower 32 bit of rax.
__ movl(rdx, rax);
__ andl(rdx, Immediate(0xFFFF));
__ imull(rdx, rdx, Immediate(18273));
__ shrl(rax, Immediate(16));
__ addl(rax, rdx);
// Save state[0].
__ movl(FieldOperand(rbx, ByteArray::kHeaderSize), rax);
// state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16)
__ movl(rdx, rcx);
__ andl(rdx, Immediate(0xFFFF));
__ imull(rdx, rdx, Immediate(36969));
__ shrl(rcx, Immediate(16));
__ addl(rcx, rdx);
// Save state[1].
__ movl(FieldOperand(rbx, ByteArray::kHeaderSize + kSeedSize), rcx);
// Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF)
__ shll(rax, Immediate(14));
__ andl(rcx, Immediate(0x3FFFF));
__ addl(rax, rcx);
__ bind(deferred->exit());
// Convert 32 random bits in rax to 0.(32 random bits) in a double
// by computing:
// ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
......@@ -2998,6 +3047,14 @@ void LCodeGen::DoRandom(LRandom* instr) {
}
void LCodeGen::DoDeferredRandom(LRandom* instr) {
__ PrepareCallCFunction(1);
__ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
// Return value is in rax.
}
void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
TranscendentalCacheStub stub(TranscendentalCache::LOG,
......
......@@ -97,6 +97,7 @@ class LCodeGen BASE_EMBEDDED {
void DoDeferredTaggedToI(LTaggedToI* instr);
void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr);
void DoDeferredStackCheck(LStackCheck* instr);
void DoDeferredRandom(LRandom* instr);
void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
void DoDeferredAllocateObject(LAllocateObject* instr);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment