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:
parent
83d912f0e4
commit
d59749f8b4
@ -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());
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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());
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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());
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user