Support inlining and crankshaft optimization of Math.random.

R=jkummerow@chromium.org
BUG=
TEST=

Review URL: http://codereview.chromium.org/9167011

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10384 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
ager@chromium.org 2012-01-11 10:35:37 +00:00
parent 83d912f0e4
commit d59749f8b4
12 changed files with 189 additions and 8 deletions

View File

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@ -1427,6 +1427,15 @@ 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(), r0);
LRandom* result = new LRandom(global_object);
return MarkAsCall(DefineFixedDouble(result, d7), instr);
}
LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
ASSERT(instr->left()->representation().IsTagged());
ASSERT(instr->right()->representation().IsTagged());

View File

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@ -141,6 +141,7 @@ class LCodeGen;
V(Parameter) \
V(Power) \
V(PushArgument) \
V(Random) \
V(RegExpLiteral) \
V(Return) \
V(ShiftI) \
@ -1026,6 +1027,17 @@ class LPower: public LTemplateInstruction<1, 2, 0> {
};
class LRandom: public LTemplateInstruction<1, 1, 0> {
public:
explicit LRandom(LOperand* global_object) {
inputs_[0] = global_object;
}
DECLARE_CONCRETE_INSTRUCTION(Random, "random")
DECLARE_HYDROGEN_ACCESSOR(Random)
};
class LArithmeticD: public LTemplateInstruction<1, 2, 0> {
public:
LArithmeticD(Token::Value op, LOperand* left, LOperand* right)

View File

@ -3195,6 +3195,30 @@ void LCodeGen::DoPower(LPower* instr) {
}
void LCodeGen::DoRandom(LRandom* 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());
__ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset));
__ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
// 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));
__ orr(r1, r1, Operand(0x300000));
// Move 0x41300000xxxxxxxx (x = random bits) to VFP.
__ vmov(d7, r0, r1);
// Move 0x4130000000000000 to VFP.
__ mov(r0, Operand(0, RelocInfo::NONE));
__ vmov(d8, r0, r1);
// Subtract and store the result in the heap number.
__ vsub(d7, d7, d8);
}
void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
ASSERT(ToDoubleRegister(instr->result()).is(d2));
TranscendentalCacheStub stub(TranscendentalCache::LOG,

View File

@ -146,6 +146,7 @@ class LChunkBuilder;
V(Parameter) \
V(Power) \
V(PushArgument) \
V(Random) \
V(RegExpLiteral) \
V(Return) \
V(Sar) \
@ -2998,6 +2999,23 @@ class HPower: public HTemplateInstruction<2> {
};
class HRandom: public HTemplateInstruction<1> {
public:
explicit HRandom(HValue* global_object) {
SetOperandAt(0, global_object);
set_representation(Representation::Double());
}
HValue* global_object() { return OperandAt(0); }
virtual Representation RequiredInputRepresentation(int index) {
return Representation::Tagged();
}
DECLARE_CONCRETE_INSTRUCTION(Random)
};
class HAdd: public HArithmeticBinaryOperation {
public:
HAdd(HValue* context, HValue* left, HValue* right)

View File

@ -5128,6 +5128,18 @@ bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr,
return true;
}
break;
case kMathRandom:
if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) {
AddCheckConstantFunction(expr, receiver, receiver_map, true);
Drop(1);
HValue* context = environment()->LookupContext();
HGlobalObject* global_object = new(zone()) HGlobalObject(context);
AddInstruction(global_object);
HRandom* result = new(zone()) HRandom(global_object);
ast_context()->ReturnInstruction(result, expr->id());
return true;
}
break;
default:
// Not yet supported for inlining.
break;
@ -6575,7 +6587,11 @@ void HGraphBuilder::GenerateLog(CallRuntime* call) {
// Fast support for Math.random().
void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) {
return Bailout("inlined runtime function: RandomHeapNumber");
HValue* context = environment()->LookupContext();
HGlobalObject* global_object = new(zone()) HGlobalObject(context);
AddInstruction(global_object);
HRandom* result = new(zone()) HRandom(global_object);
return ast_context()->ReturnInstruction(result, call->id());
}

View File

@ -3014,6 +3014,29 @@ void LCodeGen::DoPower(LPower* instr) {
}
void LCodeGen::DoRandom(LRandom* instr) {
// Having marked this instruction as a call we can use any
// registers.
ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
ASSERT(ToRegister(instr->InputAt(0)).is(eax));
__ PrepareCallCFunction(1, ebx);
__ mov(eax, FieldOperand(eax, GlobalObject::kGlobalContextOffset));
__ mov(Operand(esp, 0), eax);
__ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
// Convert 32 random bits in eax to 0.(32 random bits) in a double
// by computing:
// ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
__ mov(ebx, Immediate(0x49800000)); // 1.0 x 2^20 as single.
__ movd(xmm2, ebx);
__ movd(xmm1, eax);
__ cvtss2sd(xmm2, xmm2);
__ xorps(xmm1, xmm2);
__ subsd(xmm1, xmm2);
}
void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
ASSERT(instr->value()->Equals(instr->result()));
XMMRegister input_reg = ToDoubleRegister(instr->value());

View File

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@ -1469,6 +1469,15 @@ 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(), eax);
LRandom* result = new(zone()) LRandom(global_object);
return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
}
LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
ASSERT(instr->left()->representation().IsTagged());
ASSERT(instr->right()->representation().IsTagged());

View File

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@ -135,6 +135,7 @@ class LCodeGen;
V(OuterContext) \
V(Parameter) \
V(Power) \
V(Random) \
V(PushArgument) \
V(RegExpLiteral) \
V(Return) \
@ -1043,6 +1044,17 @@ class LPower: public LTemplateInstruction<1, 2, 0> {
};
class LRandom: public LTemplateInstruction<1, 1, 0> {
public:
explicit LRandom(LOperand* global_object) {
inputs_[0] = global_object;
}
DECLARE_CONCRETE_INSTRUCTION(Random, "random")
DECLARE_HYDROGEN_ACCESSOR(Random)
};
class LArithmeticD: public LTemplateInstruction<1, 2, 0> {
public:
LArithmeticD(Token::Value op, LOperand* left, LOperand* right)

View File

@ -4893,7 +4893,8 @@ class Script: public Struct {
V(Math, atan, MathATan) \
V(Math, exp, MathExp) \
V(Math, sqrt, MathSqrt) \
V(Math, pow, MathPow)
V(Math, pow, MathPow) \
V(Math, random, MathRandom)
enum BuiltinFunctionId {

View File

@ -2931,6 +2931,38 @@ void LCodeGen::DoPower(LPower* instr) {
}
void LCodeGen::DoRandom(LRandom* instr) {
// Having marked this instruction as a call we can use any
// registers.
ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
// Choose the right register for the first argument depending on
// calling convention.
#ifdef _WIN64
ASSERT(ToRegister(instr->InputAt(0)).is(rcx));
Register global_object = rcx;
#else
ASSERT(ToRegister(instr->InputAt(0)).is(rdi));
Register global_object = rdi;
#endif
__ PrepareCallCFunction(1);
__ movq(global_object,
FieldOperand(global_object, GlobalObject::kGlobalContextOffset));
__ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
// 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)).
__ movl(rcx, Immediate(0x49800000)); // 1.0 x 2^20 as single.
__ movd(xmm2, rcx);
__ movd(xmm1, rax);
__ cvtss2sd(xmm2, xmm2);
__ xorps(xmm1, xmm2);
__ subsd(xmm1, xmm2);
}
void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
TranscendentalCacheStub stub(TranscendentalCache::LOG,

View File

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@ -1415,6 +1415,19 @@ LInstruction* LChunkBuilder::DoPower(HPower* instr) {
}
LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
ASSERT(instr->representation().IsDouble());
ASSERT(instr->global_object()->representation().IsTagged());
#ifdef _WIN64
LOperand* global_object = UseFixed(instr->global_object(), rcx);
#else
LOperand* global_object = UseFixed(instr->global_object(), rdi);
#endif
LRandom* result = new LRandom(global_object);
return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
}
LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
ASSERT(instr->left()->representation().IsTagged());
ASSERT(instr->right()->representation().IsTagged());

View File

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@ -141,6 +141,7 @@ class LCodeGen;
V(Parameter) \
V(Power) \
V(PushArgument) \
V(Random) \
V(RegExpLiteral) \
V(Return) \
V(ShiftI) \
@ -1024,6 +1025,17 @@ class LPower: public LTemplateInstruction<1, 2, 0> {
};
class LRandom: public LTemplateInstruction<1, 1, 0> {
public:
explicit LRandom(LOperand* global_object) {
inputs_[0] = global_object;
}
DECLARE_CONCRETE_INSTRUCTION(Random, "random")
DECLARE_HYDROGEN_ACCESSOR(Random)
};
class LArithmeticD: public LTemplateInstruction<1, 2, 0> {
public:
LArithmeticD(Token::Value op, LOperand* left, LOperand* right)