Add number string cache lookup for heap numbers to generatred code (on top of the already existing smi lookup)

Added a number to string runtime function which does not try to do a cache lookup as the number is known to not be in the cahce.
Review URL: http://codereview.chromium.org/1602010

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4355 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
sgjesse@chromium.org 2010-04-07 11:13:05 +00:00
parent c33886c9b7
commit c0976e9276
6 changed files with 78 additions and 20 deletions

View File

@ -1808,11 +1808,13 @@ Object* Heap::SmiOrNumberFromDouble(double value,
}
Object* Heap::NumberToString(Object* number) {
Object* Heap::NumberToString(Object* number, bool check_number_string_cache) {
Counters::number_to_string_runtime.Increment();
Object* cached = GetNumberStringCache(number);
if (cached != undefined_value()) {
return cached;
if (check_number_string_cache) {
Object* cached = GetNumberStringCache(number);
if (cached != undefined_value()) {
return cached;
}
}
char arr[100];

View File

@ -938,7 +938,8 @@ class Heap : public AllStatic {
kRootListLength
};
static Object* NumberToString(Object* number);
static Object* NumberToString(Object* number,
bool check_number_string_cache = true);
static Map* MapForExternalArrayType(ExternalArrayType array_type);
static RootListIndex RootIndexForExternalArrayType(

View File

@ -10938,14 +10938,6 @@ void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm,
Register scratch2,
bool object_is_smi,
Label* not_found) {
// Currently only lookup for smis. Check for smi if object is not known to be
// a smi.
if (!object_is_smi) {
ASSERT(kSmiTag == 0);
__ test(object, Immediate(kSmiTagMask));
__ j(not_zero, not_found);
}
// Use of registers. Register result is used as a temporary.
Register number_string_cache = result;
Register mask = scratch1;
@ -10961,23 +10953,74 @@ void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm,
__ mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset));
__ shr(mask, 1); // Divide length by two (length is not a smi).
__ sub(Operand(mask), Immediate(1)); // Make mask.
// Calculate the entry in the number string cache. The hash value in the
// number string cache for smis is just the smi value.
__ mov(scratch, object);
__ SmiUntag(scratch);
// number string cache for smis is just the smi value, and the hash for
// doubles is the xor of the upper and lower words. See
// Heap::GetNumberStringCache.
Label smi_hash_calculated;
Label load_result_from_cache;
if (object_is_smi) {
__ mov(scratch, object);
__ SmiUntag(scratch);
} else {
Label not_smi, hash_calculated;
ASSERT(kSmiTag == 0);
__ test(object, Immediate(kSmiTagMask));
__ j(not_zero, &not_smi);
__ mov(scratch, object);
__ SmiUntag(scratch);
__ jmp(&smi_hash_calculated);
__ bind(&not_smi);
__ cmp(FieldOperand(object, HeapObject::kMapOffset),
Factory::heap_number_map());
__ j(not_equal, not_found);
ASSERT_EQ(8, kDoubleSize);
__ mov(scratch, FieldOperand(object, HeapNumber::kValueOffset));
__ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4));
// Object is heap number and hash is now in scratch. Calculate cache index.
__ and_(scratch, Operand(mask));
Register index = scratch;
Register probe = mask;
__ mov(probe,
FieldOperand(number_string_cache,
index,
times_twice_pointer_size,
FixedArray::kHeaderSize));
__ test(probe, Immediate(kSmiTagMask));
__ j(zero, not_found);
if (CpuFeatures::IsSupported(SSE2)) {
CpuFeatures::Scope fscope(SSE2);
__ movdbl(xmm0, FieldOperand(object, HeapNumber::kValueOffset));
__ movdbl(xmm1, FieldOperand(probe, HeapNumber::kValueOffset));
__ comisd(xmm0, xmm1);
} else {
__ fld_d(FieldOperand(object, HeapNumber::kValueOffset));
__ fld_d(FieldOperand(probe, HeapNumber::kValueOffset));
__ FCmp();
}
__ j(parity_even, not_found); // Bail out if NaN is involved.
__ j(not_equal, not_found); // The cache did not contain this value.
__ jmp(&load_result_from_cache);
}
__ bind(&smi_hash_calculated);
// Object is smi and hash is now in scratch. Calculate cache index.
__ and_(scratch, Operand(mask));
Register index = scratch;
// Check if the entry is the smi we are looking for.
__ cmp(object,
FieldOperand(number_string_cache,
scratch,
index,
times_twice_pointer_size,
FixedArray::kHeaderSize));
__ j(not_equal, not_found);
// Get the result from the cache.
__ bind(&load_result_from_cache);
__ mov(result,
FieldOperand(number_string_cache,
scratch,
index,
times_twice_pointer_size,
FixedArray::kHeaderSize + kPointerSize));
__ IncrementCounter(&Counters::number_to_string_native, 1);
@ -10995,7 +11038,7 @@ void NumberToStringStub::Generate(MacroAssembler* masm) {
__ bind(&runtime);
// Handle number to string in the runtime system if not found in the cache.
__ TailCallRuntime(Runtime::kNumberToString, 1, 1);
__ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1);
}

View File

@ -5249,6 +5249,17 @@ static Object* Runtime_NumberToString(Arguments args) {
}
static Object* Runtime_NumberToStringSkipCache(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 1);
Object* number = args[0];
RUNTIME_ASSERT(number->IsNumber());
return Heap::NumberToString(number, false);
}
static Object* Runtime_NumberToInteger(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 1);

View File

@ -99,6 +99,7 @@ namespace internal {
F(URIUnescape, 1, 1) \
\
F(NumberToString, 1, 1) \
F(NumberToStringSkipCache, 1, 1) \
F(NumberToInteger, 1, 1) \
F(NumberToJSUint32, 1, 1) \
F(NumberToJSInt32, 1, 1) \

View File

@ -530,7 +530,7 @@ function ToString(x) {
}
function NonStringToString(x) {
if (IS_NUMBER(x)) return %NumberToString(x);
if (IS_NUMBER(x)) return %_NumberToString(x);
if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
if (IS_UNDEFINED(x)) return 'undefined';
return (IS_NULL(x)) ? 'null' : %ToString(%DefaultString(x));