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) {
}
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);
}
......
......@@ -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);
......
......@@ -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)));
}
......
......@@ -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.
......
......@@ -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) \
......
......@@ -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);
......
......@@ -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);
......
......@@ -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
......
......@@ -890,7 +890,7 @@ void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) {
}
void CodeGenerator::GenerateRandomPositiveSmi(ZoneList<Expression*>* args) {
void CodeGenerator::GenerateRandomHeapNumber(ZoneList<Expression*>* args) {
UNIMPLEMENTED_MIPS();
}
......
......@@ -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);
......
......@@ -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(),
......
......@@ -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
......@@ -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();
......
......@@ -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);
}
......
......@@ -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);
......
......@@ -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);
}
......
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