Change Math.random() to return 32 bits of random goodness, instead of 30 random bits...
authorwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 7 Apr 2010 08:18:51 +0000 (08:18 +0000)
committerwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 7 Apr 2010 08:18:51 +0000 (08:18 +0000)
Review URL: http://codereview.chromium.org/1599019

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4354 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

16 files changed:
src/arm/codegen-arm.cc
src/arm/codegen-arm.h
src/assembler.cc
src/assembler.h
src/codegen.h
src/ia32/codegen-ia32.cc
src/ia32/codegen-ia32.h
src/math.js
src/mips/codegen-mips.cc
src/mips/codegen-mips.h
src/serialize.cc
src/v8.cc
src/v8.h
src/x64/codegen-x64.cc
src/x64/codegen-x64.h
test/cctest/test-log-stack-tracer.cc

index 4e0801a1b72f748b664395b50d4cc55d24079923..60bc84820ca0bfa0dbe5e43dc979a6481724f0e4 100644 (file)
@@ -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;
   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);
 }
index 0d1a3855975816820d0e91c5ed5e6cad6b21f841..c1201804a99651f0575cc3d57f281d9f731ec0ff 100644 (file)
@@ -387,7 +387,7 @@ class CodeGenerator: public AstVisitor {
   void GenerateLog(ZoneList<Expression*>* args);
 
   // Fast support for Math.random().
-  void GenerateRandomPositiveSmi(ZoneList<Expression*>* args);
+  void GenerateRandomHeapNumber(ZoneList<Expression*>* args);
 
   // Fast support for StringAdd.
   void GenerateStringAdd(ZoneList<Expression*>* args);
index bb010c829f4986f3b2f440df299f81acc259c4e9..c93cbf55a8b4ff04bb331c5042f07c2606f3d8e6 100644 (file)
@@ -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)));
 }
 
 
index b4834e53f85d6a43b3e979a94c1dfa59ca27d9d3..68c6f4fdde9174daceb9ca4a84b5af89b71ab73e 100644 (file)
@@ -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.
index 9685ee7d0a3c12cf3e01f3605241a465ea542dfb..c3812fb6861b27ad07136cc4149ba6d6d9e8d891 100644 (file)
@@ -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)                                              \
index ee8238aef15b014a0f801e73951203a6319c16fc..29ec293cb83418d0bdb068adadac2eb40d1067b5 100644 (file)
@@ -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);
   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);
index a92386fe20bd4e0fe7a276b8a594473f606bba5d..a9dafa70ea9bb5d220859cd5c68ae8fac74cc3ff 100644 (file)
@@ -614,7 +614,7 @@ class CodeGenerator: public AstVisitor {
   void GenerateGetFramePointer(ZoneList<Expression*>* args);
 
   // Fast support for Math.random().
-  void GenerateRandomPositiveSmi(ZoneList<Expression*>* args);
+  void GenerateRandomHeapNumber(ZoneList<Expression*>* args);
 
   // Fast support for StringAdd.
   void GenerateStringAdd(ZoneList<Expression*>* args);
index d17a6fdf5b0d7a992110bad7b81680cdcefe9b7b..fc3b132fffac570631aebfeff25b2a8f5c2796d1 100644 (file)
@@ -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
index 0936a6d7d694c9accb2eb49f7c3495eac08425a6..ca1edd46b8b3f3f555a2863f65478cd5424a2f99 100644 (file)
@@ -890,7 +890,7 @@ void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) {
 }
 
 
-void CodeGenerator::GenerateRandomPositiveSmi(ZoneList<Expression*>* args) {
+void CodeGenerator::GenerateRandomHeapNumber(ZoneList<Expression*>* args) {
   UNIMPLEMENTED_MIPS();
 }
 
index 44a4a62f29852ec43f6c17dbc4caa64f715d17da..0f0a7462f74be1276355a2d7c02842956dca63c4 100644 (file)
@@ -352,7 +352,7 @@ class CodeGenerator: public AstVisitor {
   void GenerateLog(ZoneList<Expression*>* args);
 
   // Fast support for Math.random().
-  void GenerateRandomPositiveSmi(ZoneList<Expression*>* args);
+  void GenerateRandomHeapNumber(ZoneList<Expression*>* args);
 
   void GenerateIsObject(ZoneList<Expression*>* args);
   void GenerateIsFunction(ZoneList<Expression*>* args);
index 980a1bc449e4b1615340048a5969cf208132d768..d728fc4e5255756ddaaaa149475b5b434a9ec831 100644 (file)
@@ -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(),
index 2fe672d86fbd4f6565166f287289e8fdab8332b6..dd98e6155ddfdaf735a8b01520d9060aad9262bf 100644 (file)
--- 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<uint32_t>(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<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
index 4fc44c2f0558386e5a5b7be6c37eb247c77433e3..cf660a2680b6a876618c78010a1669ba413df406 100644 (file)
--- 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();
index e0351040039e878326f4dc6f90ea6bde9adc3455..3b03477c45ba06d69bde43b3021a7483204b7832 100644 (file)
@@ -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);
   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);
 }
index 8eea47959cb8a9e083c21e1fae61ddaaf7e55976..35e1f4439ab724b6135eadc3335be7110bae7dcd 100644 (file)
@@ -568,7 +568,7 @@ class CodeGenerator: public AstVisitor {
   void GenerateGetFramePointer(ZoneList<Expression*>* args);
 
   // Fast support for Math.random().
-  void GenerateRandomPositiveSmi(ZoneList<Expression*>* args);
+  void GenerateRandomHeapNumber(ZoneList<Expression*>* args);
 
   // Fast support for StringAdd.
   void GenerateStringAdd(ZoneList<Expression*>* args);
index 532311bfbc212a31cccccacaf7e9674997f62615..4d9d75927d1a18e8f6d69bd8cac71d6b9126119b 100644 (file)
@@ -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);
   }