}
-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);
}
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);
}
-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)));
}
// 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.
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) \
}
-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);
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);
// ECMA 262 - 15.8.2.14
function MathRandom() {
- return %_RandomPositiveSmi() / 0x40000000;
+ return %_RandomHeapNumber();
}
// ECMA 262 - 15.8.2.15
}
-void CodeGenerator::GenerateRandomPositiveSmi(ZoneList<Expression*>* args) {
+void CodeGenerator::GenerateRandomHeapNumber(ZoneList<Expression*>* args) {
UNIMPLEMENTED_MIPS();
}
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);
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(),
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
// 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();
}
-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);
}
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);
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);
}