Revision: 4355
Author: [email protected]
Date: Wed Apr 7 04:13:05 2010
Log: 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
http://code.google.com/p/v8/source/detail?r=4355
Modified:
/branches/bleeding_edge/src/heap.cc
/branches/bleeding_edge/src/heap.h
/branches/bleeding_edge/src/ia32/codegen-ia32.cc
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/runtime.h
/branches/bleeding_edge/src/runtime.js
=======================================
--- /branches/bleeding_edge/src/heap.cc Tue Mar 30 05:01:06 2010
+++ /branches/bleeding_edge/src/heap.cc Wed Apr 7 04:13:05 2010
@@ -1808,11 +1808,13 @@
}
-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];
=======================================
--- /branches/bleeding_edge/src/heap.h Tue Mar 30 05:01:06 2010
+++ /branches/bleeding_edge/src/heap.h Wed Apr 7 04:13:05 2010
@@ -938,7 +938,8 @@
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(
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Wed Apr 7 01:18:51
2010
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Wed Apr 7 04:13:05
2010
@@ -10938,14 +10938,6 @@
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 @@
__ 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, ¬_smi);
+ __ mov(scratch, object);
+ __ SmiUntag(scratch);
+ __ jmp(&smi_hash_calculated);
+ __ bind(¬_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 @@
__ 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);
}
=======================================
--- /branches/bleeding_edge/src/runtime.cc Tue Apr 6 10:58:28 2010
+++ /branches/bleeding_edge/src/runtime.cc Wed Apr 7 04:13:05 2010
@@ -5247,6 +5247,17 @@
return Heap::NumberToString(number);
}
+
+
+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) {
=======================================
--- /branches/bleeding_edge/src/runtime.h Tue Apr 6 10:58:28 2010
+++ /branches/bleeding_edge/src/runtime.h Wed Apr 7 04:13:05 2010
@@ -99,6 +99,7 @@
F(URIUnescape, 1, 1) \
\
F(NumberToString, 1, 1) \
+ F(NumberToStringSkipCache, 1, 1) \
F(NumberToInteger, 1, 1) \
F(NumberToJSUint32, 1, 1) \
F(NumberToJSInt32, 1, 1) \
=======================================
--- /branches/bleeding_edge/src/runtime.js Tue Mar 30 00:15:23 2010
+++ /branches/bleeding_edge/src/runtime.js Wed Apr 7 04:13:05 2010
@@ -530,7 +530,7 @@
}
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));
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
To unsubscribe, reply using "remove me" as the subject.