Reviewers: Erik Corry,

Description:
Port improvement to Math.random to ARM. According to issue #670,
Math.random was sped up on ia32 and x64 by creating a generated
function RandomHeapNumber, whose body is inline assembly code
that allocates a heap number, calls V8::Random to get a random
uint32, and puts the uint32 divided by 2^32 into the heapnumber.

BUG=none
TEST=none


Please review this at http://codereview.chromium.org/1689007/show

SVN Base: http://v8.googlecode.com/svn/branches/bleeding_edge/

Affected files:
  M     src/arm/codegen-arm.cc


Index: src/arm/codegen-arm.cc
===================================================================
--- src/arm/codegen-arm.cc      (revision 4475)
+++ src/arm/codegen-arm.cc      (working copy)
@@ -4232,19 +4232,49 @@
   Label slow_allocate_heapnumber;
   Label heapnumber_allocated;

-  __ AllocateHeapNumber(r0, r1, r2, &slow_allocate_heapnumber);
+  __ AllocateHeapNumber(r4, r1, r2, &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.
   __ mov(r0, Operand(Smi::FromInt(0)));
   __ push(r0);
   __ CallRuntime(Runtime::kNumberUnaryMinus, 1);
+  __ mov(r4, Operand(r0));

   __ bind(&heapnumber_allocated);
-  __ PrepareCallCFunction(1, r1);
-  __ CallCFunction(
-      ExternalReference::fill_heap_number_with_random_function(), 1);
-  frame_->EmitPush(r0);
+
+  // Convert 32 random bits in r0 to 0.(32 random bits) in a double
+  // by computing:
+  // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
+  if (CpuFeatures::IsSupported(VFP3)) {
+    __ PrepareCallCFunction(0, r1);
+    __ CallCFunction(ExternalReference::random_uint32_function(), 0);
+
+    CpuFeatures::Scope scope(VFP3);
+    // 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));
+    __ vmov(d8, r0, r1);
+    // Subtract and store the result in the heap number.
+    __ vsub(d7, d7, d8);
+    __ sub(r0, r4, Operand(kHeapObjectTag));
+    __ vstr(d7, r0, HeapNumber::kValueOffset);
+    frame_->EmitPush(r4);
+  } else {
+    __ mov(r0, Operand(r4));
+    __ PrepareCallCFunction(1, r1);
+    __ CallCFunction(
+        ExternalReference::fill_heap_number_with_random_function(), 1);
+    frame_->EmitPush(r0);
+  }
 }




--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to