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, &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 @@

   __ 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.

Reply via email to