From: whesse@chromium.org Date: Wed, 7 Apr 2010 08:18:51 +0000 (+0000) Subject: Change Math.random() to return 32 bits of random goodness, instead of 30 random bits... X-Git-Tag: upstream/4.7.83~22065 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c33886c9b7b5a5e1a08ca15c5a8319a5b71e7643;p=platform%2Fupstream%2Fv8.git 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 --- diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc index 4e0801a1b..60bc84820 100644 --- a/src/arm/codegen-arm.cc +++ b/src/arm/codegen-arm.cc @@ -3624,10 +3624,24 @@ void CodeGenerator::GenerateArguments(ZoneList* args) { } -void CodeGenerator::GenerateRandomPositiveSmi(ZoneList* args) { +void CodeGenerator::GenerateRandomHeapNumber( + ZoneList* args) { VirtualFrame::SpilledScope spilled_scope; 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); frame_->EmitPush(r0); } diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h index 0d1a38559..c1201804a 100644 --- a/src/arm/codegen-arm.h +++ b/src/arm/codegen-arm.h @@ -387,7 +387,7 @@ class CodeGenerator: public AstVisitor { void GenerateLog(ZoneList* args); // Fast support for Math.random(). - void GenerateRandomPositiveSmi(ZoneList* args); + void GenerateRandomHeapNumber(ZoneList* args); // Fast support for StringAdd. void GenerateStringAdd(ZoneList* args); diff --git a/src/assembler.cc b/src/assembler.cc index bb010c829..c93cbf55a 100644 --- a/src/assembler.cc +++ b/src/assembler.cc @@ -574,8 +574,9 @@ ExternalReference ExternalReference::perform_gc_function() { } -ExternalReference ExternalReference::random_positive_smi_function() { - return ExternalReference(Redirect(FUNCTION_ADDR(V8::RandomPositiveSmi))); +ExternalReference ExternalReference::fill_heap_number_with_random_function() { + return + ExternalReference(Redirect(FUNCTION_ADDR(V8::FillHeapNumberWithRandom))); } diff --git a/src/assembler.h b/src/assembler.h index b4834e53f..68c6f4fdd 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -398,7 +398,7 @@ class ExternalReference BASE_EMBEDDED { // ExternalReferenceTable in serialize.cc manually. 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 data in the keyed lookup cache. diff --git a/src/codegen.h b/src/codegen.h index 9685ee7d0..c3812fb68 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -114,7 +114,7 @@ namespace internal { F(CharFromCode, 1, 1) \ F(ObjectEquals, 2, 1) \ F(Log, 3, 1) \ - F(RandomPositiveSmi, 0, 1) \ + F(RandomHeapNumber, 0, 1) \ F(IsObject, 1, 1) \ F(IsFunction, 1, 1) \ F(IsUndetectableObject, 1, 1) \ diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc index ee8238aef..29ec293cb 100644 --- a/src/ia32/codegen-ia32.cc +++ b/src/ia32/codegen-ia32.cc @@ -6430,16 +6430,30 @@ void CodeGenerator::GenerateGetFramePointer(ZoneList* args) { } -void CodeGenerator::GenerateRandomPositiveSmi(ZoneList* args) { +void CodeGenerator::GenerateRandomHeapNumber( + ZoneList* args) { ASSERT(args->length() == 0); frame_->SpillAll(); - static const int num_arguments = 0; - __ PrepareCallCFunction(num_arguments, eax); + Label slow_allocate_heapnumber; + Label heapnumber_allocated; - // Call V8::RandomPositiveSmi(). - __ CallCFunction(ExternalReference::random_positive_smi_function(), - num_arguments); + __ AllocateHeapNumber(eax, ebx, ecx, &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(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); frame_->Push(&result); diff --git a/src/ia32/codegen-ia32.h b/src/ia32/codegen-ia32.h index a92386fe2..a9dafa70e 100644 --- a/src/ia32/codegen-ia32.h +++ b/src/ia32/codegen-ia32.h @@ -614,7 +614,7 @@ class CodeGenerator: public AstVisitor { void GenerateGetFramePointer(ZoneList* args); // Fast support for Math.random(). - void GenerateRandomPositiveSmi(ZoneList* args); + void GenerateRandomHeapNumber(ZoneList* args); // Fast support for StringAdd. void GenerateStringAdd(ZoneList* args); diff --git a/src/math.js b/src/math.js index d17a6fdf5..fc3b132ff 100644 --- a/src/math.js +++ b/src/math.js @@ -165,7 +165,7 @@ function MathPow(x, y) { // ECMA 262 - 15.8.2.14 function MathRandom() { - return %_RandomPositiveSmi() / 0x40000000; + return %_RandomHeapNumber(); } // ECMA 262 - 15.8.2.15 diff --git a/src/mips/codegen-mips.cc b/src/mips/codegen-mips.cc index 0936a6d7d..ca1edd46b 100644 --- a/src/mips/codegen-mips.cc +++ b/src/mips/codegen-mips.cc @@ -890,7 +890,7 @@ void CodeGenerator::GenerateArguments(ZoneList* args) { } -void CodeGenerator::GenerateRandomPositiveSmi(ZoneList* args) { +void CodeGenerator::GenerateRandomHeapNumber(ZoneList* args) { UNIMPLEMENTED_MIPS(); } diff --git a/src/mips/codegen-mips.h b/src/mips/codegen-mips.h index 44a4a62f2..0f0a7462f 100644 --- a/src/mips/codegen-mips.h +++ b/src/mips/codegen-mips.h @@ -352,7 +352,7 @@ class CodeGenerator: public AstVisitor { void GenerateLog(ZoneList* args); // Fast support for Math.random(). - void GenerateRandomPositiveSmi(ZoneList* args); + void GenerateRandomHeapNumber(ZoneList* args); void GenerateIsObject(ZoneList* args); void GenerateIsFunction(ZoneList* args); diff --git a/src/serialize.cc b/src/serialize.cc index 980a1bc44..d728fc4e5 100644 --- a/src/serialize.cc +++ b/src/serialize.cc @@ -329,10 +329,10 @@ void ExternalReferenceTable::PopulateTable() { RUNTIME_ENTRY, 1, "Runtime::PerformGC"); - Add(ExternalReference::random_positive_smi_function().address(), + Add(ExternalReference::fill_heap_number_with_random_function().address(), RUNTIME_ENTRY, 2, - "V8::RandomPositiveSmi"); + "V8::FillHeapNumberWithRandom"); // Miscellaneous Add(ExternalReference::the_hole_value_location().address(), diff --git a/src/v8.cc b/src/v8.cc index 2fe672d86..dd98e6155 100644 --- a/src/v8.cc +++ b/src/v8.cc @@ -208,14 +208,27 @@ bool V8::IdleNotification() { return Heap::IdleNotification(); } -static const uint32_t kRandomPositiveSmiMax = 0x3fffffff; - -Smi* V8::RandomPositiveSmi() { - uint32_t random = Random(); - ASSERT(static_cast(Smi::kMaxValue) >= kRandomPositiveSmiMax); - // kRandomPositiveSmiMax must match the value being divided - // by in math.js. - return Smi::FromInt(random & kRandomPositiveSmiMax); + +// Use a union type to avoid type-aliasing optimizations in GCC. +typedef union { + double double_value; + uint64_t uint64_t_value; +} double_int_union; + + +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( + reinterpret_cast(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 diff --git a/src/v8.h b/src/v8.h index 4fc44c2f0..cf660a268 100644 --- a/src/v8.h +++ b/src/v8.h @@ -95,7 +95,7 @@ class V8 : public AllStatic { // Random number generation support. Not cryptographically safe. static uint32_t Random(); - static Smi* RandomPositiveSmi(); + static Object* FillHeapNumberWithRandom(Object* heap_number); // Idle notification directly from the API. static bool IdleNotification(); diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc index e03510400..3b03477c4 100644 --- a/src/x64/codegen-x64.cc +++ b/src/x64/codegen-x64.cc @@ -4074,19 +4074,41 @@ void CodeGenerator::GenerateGetFramePointer(ZoneList* args) { } -void CodeGenerator::GenerateRandomPositiveSmi(ZoneList* args) { +void CodeGenerator::GenerateRandomHeapNumber( + ZoneList* args) { ASSERT(args->length() == 0); frame_->SpillAll(); - __ push(rsi); - static const int num_arguments = 0; - __ PrepareCallCFunction(num_arguments); + Label slow_allocate_heapnumber; + 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(). - __ CallCFunction(ExternalReference::random_positive_smi_function(), - num_arguments); + __ bind(&heapnumber_allocated); + // 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); +#endif Result result = allocator_->Allocate(rax); frame_->Push(&result); } diff --git a/src/x64/codegen-x64.h b/src/x64/codegen-x64.h index 8eea47959..35e1f4439 100644 --- a/src/x64/codegen-x64.h +++ b/src/x64/codegen-x64.h @@ -568,7 +568,7 @@ class CodeGenerator: public AstVisitor { void GenerateGetFramePointer(ZoneList* args); // Fast support for Math.random(). - void GenerateRandomPositiveSmi(ZoneList* args); + void GenerateRandomHeapNumber(ZoneList* args); // Fast support for StringAdd. void GenerateStringAdd(ZoneList* args); diff --git a/test/cctest/test-log-stack-tracer.cc b/test/cctest/test-log-stack-tracer.cc index 532311bfb..4d9d75927 100644 --- a/test/cctest/test-log-stack-tracer.cc +++ b/test/cctest/test-log-stack-tracer.cc @@ -235,11 +235,11 @@ class CodeGeneratorPatcher { CodeGeneratorPatcher() { CodeGenerator::InlineRuntimeLUT genGetFramePointer = {&CodeGenerator::GenerateGetFramePointer, "_GetFramePointer", 0}; - // _RandomPositiveSmi is not used in our tests. The one we replace need to - // have the same number of arguments as the one we put in, which is zero in - // this case. + // _RandomHeapNumber is just used as a dummy function that has zero + // arguments, the same as the _GetFramePointer function we actually patch + // in. bool result = CodeGenerator::PatchInlineRuntimeEntry( - NewString("_RandomPositiveSmi"), + NewString("_RandomHeapNumber"), genGetFramePointer, &oldInlineEntry); CHECK(result); }