Commit c33886c9 authored by whesse@chromium.org's avatar whesse@chromium.org

Change Math.random() to return 32 bits of random goodness, instead of 30...

Change Math.random() to return 32 bits of random goodness, instead of 30 random bits.  Math.random now allocates a HeapNumber inline, and calls a C funciton directly to put the random bits into it.
Review URL: http://codereview.chromium.org/1599019

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4354 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d73f9f0f
...@@ -3624,10 +3624,24 @@ void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) { ...@@ -3624,10 +3624,24 @@ void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) {
} }
void CodeGenerator::GenerateRandomPositiveSmi(ZoneList<Expression*>* args) { void CodeGenerator::GenerateRandomHeapNumber(
ZoneList<Expression*>* args) {
VirtualFrame::SpilledScope spilled_scope; VirtualFrame::SpilledScope spilled_scope;
ASSERT(args->length() == 0); ASSERT(args->length() == 0);
__ Call(ExternalReference::random_positive_smi_function().address(),
Label slow_allocate_heapnumber;
Label heapnumber_allocated;
__ AllocateHeapNumber(r0, r1, r2, &slow_allocate_heapnumber);
__ jmp(&heapnumber_allocated);
__ bind(&slow_allocate_heapnumber);
__ mov(r0, Operand(Smi::FromInt(0)));
__ push(r0);
__ CallRuntime(Runtime::kNumberUnaryMinus, 1);
__ bind(&heapnumber_allocated);
__ Call(ExternalReference::fill_heap_number_with_random_function().address(),
RelocInfo::RUNTIME_ENTRY); RelocInfo::RUNTIME_ENTRY);
frame_->EmitPush(r0); frame_->EmitPush(r0);
} }
......
...@@ -387,7 +387,7 @@ class CodeGenerator: public AstVisitor { ...@@ -387,7 +387,7 @@ class CodeGenerator: public AstVisitor {
void GenerateLog(ZoneList<Expression*>* args); void GenerateLog(ZoneList<Expression*>* args);
// Fast support for Math.random(). // Fast support for Math.random().
void GenerateRandomPositiveSmi(ZoneList<Expression*>* args); void GenerateRandomHeapNumber(ZoneList<Expression*>* args);
// Fast support for StringAdd. // Fast support for StringAdd.
void GenerateStringAdd(ZoneList<Expression*>* args); void GenerateStringAdd(ZoneList<Expression*>* args);
......
...@@ -574,8 +574,9 @@ ExternalReference ExternalReference::perform_gc_function() { ...@@ -574,8 +574,9 @@ ExternalReference ExternalReference::perform_gc_function() {
} }
ExternalReference ExternalReference::random_positive_smi_function() { ExternalReference ExternalReference::fill_heap_number_with_random_function() {
return ExternalReference(Redirect(FUNCTION_ADDR(V8::RandomPositiveSmi))); return
ExternalReference(Redirect(FUNCTION_ADDR(V8::FillHeapNumberWithRandom)));
} }
......
...@@ -398,7 +398,7 @@ class ExternalReference BASE_EMBEDDED { ...@@ -398,7 +398,7 @@ class ExternalReference BASE_EMBEDDED {
// ExternalReferenceTable in serialize.cc manually. // ExternalReferenceTable in serialize.cc manually.
static ExternalReference perform_gc_function(); static ExternalReference perform_gc_function();
static ExternalReference random_positive_smi_function(); static ExternalReference fill_heap_number_with_random_function();
static ExternalReference transcendental_cache_array_address(); static ExternalReference transcendental_cache_array_address();
// Static data in the keyed lookup cache. // Static data in the keyed lookup cache.
......
...@@ -114,7 +114,7 @@ namespace internal { ...@@ -114,7 +114,7 @@ namespace internal {
F(CharFromCode, 1, 1) \ F(CharFromCode, 1, 1) \
F(ObjectEquals, 2, 1) \ F(ObjectEquals, 2, 1) \
F(Log, 3, 1) \ F(Log, 3, 1) \
F(RandomPositiveSmi, 0, 1) \ F(RandomHeapNumber, 0, 1) \
F(IsObject, 1, 1) \ F(IsObject, 1, 1) \
F(IsFunction, 1, 1) \ F(IsFunction, 1, 1) \
F(IsUndetectableObject, 1, 1) \ F(IsUndetectableObject, 1, 1) \
......
...@@ -6430,16 +6430,30 @@ void CodeGenerator::GenerateGetFramePointer(ZoneList<Expression*>* args) { ...@@ -6430,16 +6430,30 @@ void CodeGenerator::GenerateGetFramePointer(ZoneList<Expression*>* args) {
} }
void CodeGenerator::GenerateRandomPositiveSmi(ZoneList<Expression*>* args) { void CodeGenerator::GenerateRandomHeapNumber(
ZoneList<Expression*>* args) {
ASSERT(args->length() == 0); ASSERT(args->length() == 0);
frame_->SpillAll(); frame_->SpillAll();
static const int num_arguments = 0; Label slow_allocate_heapnumber;
__ PrepareCallCFunction(num_arguments, eax); Label heapnumber_allocated;
// Call V8::RandomPositiveSmi(). __ AllocateHeapNumber(eax, ebx, ecx, &slow_allocate_heapnumber);
__ CallCFunction(ExternalReference::random_positive_smi_function(), __ jmp(&heapnumber_allocated);
num_arguments);
__ bind(&slow_allocate_heapnumber);
// To allocate a heap number, and ensure that it is not a smi, we
// call the runtime function FUnaryMinus on 0, returning the double
// -0.0. A new, distinct heap number is returned each time.
__ push(Immediate(Smi::FromInt(0)));
__ CallRuntime(Runtime::kNumberUnaryMinus, 1);
__ bind(&heapnumber_allocated);
__ PrepareCallCFunction(1, ebx);
__ mov(Operand(esp, 0), eax);
__ CallCFunction(ExternalReference::fill_heap_number_with_random_function(),
1);
Result result = allocator_->Allocate(eax); Result result = allocator_->Allocate(eax);
frame_->Push(&result); frame_->Push(&result);
......
...@@ -614,7 +614,7 @@ class CodeGenerator: public AstVisitor { ...@@ -614,7 +614,7 @@ class CodeGenerator: public AstVisitor {
void GenerateGetFramePointer(ZoneList<Expression*>* args); void GenerateGetFramePointer(ZoneList<Expression*>* args);
// Fast support for Math.random(). // Fast support for Math.random().
void GenerateRandomPositiveSmi(ZoneList<Expression*>* args); void GenerateRandomHeapNumber(ZoneList<Expression*>* args);
// Fast support for StringAdd. // Fast support for StringAdd.
void GenerateStringAdd(ZoneList<Expression*>* args); void GenerateStringAdd(ZoneList<Expression*>* args);
......
...@@ -165,7 +165,7 @@ function MathPow(x, y) { ...@@ -165,7 +165,7 @@ function MathPow(x, y) {
// ECMA 262 - 15.8.2.14 // ECMA 262 - 15.8.2.14
function MathRandom() { function MathRandom() {
return %_RandomPositiveSmi() / 0x40000000; return %_RandomHeapNumber();
} }
// ECMA 262 - 15.8.2.15 // ECMA 262 - 15.8.2.15
......
...@@ -890,7 +890,7 @@ void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) { ...@@ -890,7 +890,7 @@ void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) {
} }
void CodeGenerator::GenerateRandomPositiveSmi(ZoneList<Expression*>* args) { void CodeGenerator::GenerateRandomHeapNumber(ZoneList<Expression*>* args) {
UNIMPLEMENTED_MIPS(); UNIMPLEMENTED_MIPS();
} }
......
...@@ -352,7 +352,7 @@ class CodeGenerator: public AstVisitor { ...@@ -352,7 +352,7 @@ class CodeGenerator: public AstVisitor {
void GenerateLog(ZoneList<Expression*>* args); void GenerateLog(ZoneList<Expression*>* args);
// Fast support for Math.random(). // Fast support for Math.random().
void GenerateRandomPositiveSmi(ZoneList<Expression*>* args); void GenerateRandomHeapNumber(ZoneList<Expression*>* args);
void GenerateIsObject(ZoneList<Expression*>* args); void GenerateIsObject(ZoneList<Expression*>* args);
void GenerateIsFunction(ZoneList<Expression*>* args); void GenerateIsFunction(ZoneList<Expression*>* args);
......
...@@ -329,10 +329,10 @@ void ExternalReferenceTable::PopulateTable() { ...@@ -329,10 +329,10 @@ void ExternalReferenceTable::PopulateTable() {
RUNTIME_ENTRY, RUNTIME_ENTRY,
1, 1,
"Runtime::PerformGC"); "Runtime::PerformGC");
Add(ExternalReference::random_positive_smi_function().address(), Add(ExternalReference::fill_heap_number_with_random_function().address(),
RUNTIME_ENTRY, RUNTIME_ENTRY,
2, 2,
"V8::RandomPositiveSmi"); "V8::FillHeapNumberWithRandom");
// Miscellaneous // Miscellaneous
Add(ExternalReference::the_hole_value_location().address(), Add(ExternalReference::the_hole_value_location().address(),
......
...@@ -208,14 +208,27 @@ bool V8::IdleNotification() { ...@@ -208,14 +208,27 @@ bool V8::IdleNotification() {
return Heap::IdleNotification(); return Heap::IdleNotification();
} }
static const uint32_t kRandomPositiveSmiMax = 0x3fffffff;
// Use a union type to avoid type-aliasing optimizations in GCC.
Smi* V8::RandomPositiveSmi() { typedef union {
uint32_t random = Random(); double double_value;
ASSERT(static_cast<uint32_t>(Smi::kMaxValue) >= kRandomPositiveSmiMax); uint64_t uint64_t_value;
// kRandomPositiveSmiMax must match the value being divided } double_int_union;
// by in math.js.
return Smi::FromInt(random & kRandomPositiveSmiMax);
Object* V8::FillHeapNumberWithRandom(Object* heap_number) {
uint64_t random_bits = Random();
// Make a double* from address (heap_number + sizeof(double)).
double_int_union* r = reinterpret_cast<double_int_union*>(
reinterpret_cast<char*>(heap_number) +
HeapNumber::kValueOffset - kHeapObjectTag);
// Create a random number between 0.0 and 1.0 by putting random bits into
// the mantissa of 1.0 and subtracting 1.0.
r->double_value = 1.0;
r->uint64_t_value |= (random_bits << 20);
r->double_value -= 1.0; // Force into the range [0.0, 1.0).
return heap_number;
} }
} } // namespace v8::internal } } // namespace v8::internal
...@@ -95,7 +95,7 @@ class V8 : public AllStatic { ...@@ -95,7 +95,7 @@ class V8 : public AllStatic {
// Random number generation support. Not cryptographically safe. // Random number generation support. Not cryptographically safe.
static uint32_t Random(); static uint32_t Random();
static Smi* RandomPositiveSmi(); static Object* FillHeapNumberWithRandom(Object* heap_number);
// Idle notification directly from the API. // Idle notification directly from the API.
static bool IdleNotification(); static bool IdleNotification();
......
...@@ -4074,19 +4074,41 @@ void CodeGenerator::GenerateGetFramePointer(ZoneList<Expression*>* args) { ...@@ -4074,19 +4074,41 @@ void CodeGenerator::GenerateGetFramePointer(ZoneList<Expression*>* args) {
} }
void CodeGenerator::GenerateRandomPositiveSmi(ZoneList<Expression*>* args) { void CodeGenerator::GenerateRandomHeapNumber(
ZoneList<Expression*>* args) {
ASSERT(args->length() == 0); ASSERT(args->length() == 0);
frame_->SpillAll(); frame_->SpillAll();
__ push(rsi);
static const int num_arguments = 0; Label slow_allocate_heapnumber;
__ PrepareCallCFunction(num_arguments); Label heapnumber_allocated;
__ AllocateHeapNumber(rdi, rbx, &slow_allocate_heapnumber);
__ jmp(&heapnumber_allocated);
__ bind(&slow_allocate_heapnumber);
// To allocate a heap number, and ensure that it is not a smi, we
// call the runtime function FUnaryMinus on 0, returning the double
// -0.0. A new, distinct heap number is returned each time.
__ Push(Smi::FromInt(0));
__ CallRuntime(Runtime::kNumberUnaryMinus, 1);
__ movq(rdi, rax);
// Call V8::RandomPositiveSmi(). __ bind(&heapnumber_allocated);
__ CallCFunction(ExternalReference::random_positive_smi_function(),
num_arguments);
// Put a random number into the heap number rdi using a C++ function.
// Return the heap number in rax.
#ifdef _WIN64
__ movq(rcx, rdi);
#else
// Callee-save in Microsoft 64-bit ABI, but not in AMD64 ABI.
__ push(rsi);
#endif
__ PrepareCallCFunction(1);
__ CallCFunction(ExternalReference::fill_heap_number_with_random_function(),
1);
#ifndef _WIN64
// Callee-save in Microsoft 64-bit ABI, but not in AMD64 ABI.
__ pop(rsi); __ pop(rsi);
#endif
Result result = allocator_->Allocate(rax); Result result = allocator_->Allocate(rax);
frame_->Push(&result); frame_->Push(&result);
} }
......
...@@ -568,7 +568,7 @@ class CodeGenerator: public AstVisitor { ...@@ -568,7 +568,7 @@ class CodeGenerator: public AstVisitor {
void GenerateGetFramePointer(ZoneList<Expression*>* args); void GenerateGetFramePointer(ZoneList<Expression*>* args);
// Fast support for Math.random(). // Fast support for Math.random().
void GenerateRandomPositiveSmi(ZoneList<Expression*>* args); void GenerateRandomHeapNumber(ZoneList<Expression*>* args);
// Fast support for StringAdd. // Fast support for StringAdd.
void GenerateStringAdd(ZoneList<Expression*>* args); void GenerateStringAdd(ZoneList<Expression*>* args);
......
...@@ -235,11 +235,11 @@ class CodeGeneratorPatcher { ...@@ -235,11 +235,11 @@ class CodeGeneratorPatcher {
CodeGeneratorPatcher() { CodeGeneratorPatcher() {
CodeGenerator::InlineRuntimeLUT genGetFramePointer = CodeGenerator::InlineRuntimeLUT genGetFramePointer =
{&CodeGenerator::GenerateGetFramePointer, "_GetFramePointer", 0}; {&CodeGenerator::GenerateGetFramePointer, "_GetFramePointer", 0};
// _RandomPositiveSmi is not used in our tests. The one we replace need to // _RandomHeapNumber is just used as a dummy function that has zero
// have the same number of arguments as the one we put in, which is zero in // arguments, the same as the _GetFramePointer function we actually patch
// this case. // in.
bool result = CodeGenerator::PatchInlineRuntimeEntry( bool result = CodeGenerator::PatchInlineRuntimeEntry(
NewString("_RandomPositiveSmi"), NewString("_RandomHeapNumber"),
genGetFramePointer, &oldInlineEntry); genGetFramePointer, &oldInlineEntry);
CHECK(result); CHECK(result);
} }
......
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