Revision: 3843
Author: [email protected]
Date: Fri Feb 12 03:55:04 2010
Log: Optimize string plus smi

When adding a string with a smi value the number string cache is checked in generated code. If the there is a string value in the number string cache the resulting string is produced in generated code.
Review URL: http://codereview.chromium.org/596082
http://code.google.com/p/v8/source/detail?r=3843

Modified:
 /branches/bleeding_edge/src/ia32/assembler-ia32.h
 /branches/bleeding_edge/src/ia32/codegen-ia32.cc
 /branches/bleeding_edge/src/v8-counters.h

=======================================
--- /branches/bleeding_edge/src/ia32/assembler-ia32.h Thu Feb 4 13:32:02 2010 +++ /branches/bleeding_edge/src/ia32/assembler-ia32.h Fri Feb 12 03:55:04 2010
@@ -231,7 +231,8 @@
   times_8 = 3,
   times_int_size = times_4,
   times_half_pointer_size = times_2,
-  times_pointer_size = times_4
+  times_pointer_size = times_4,
+  times_twice_pointer_size = times_8
 };


=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Feb 12 03:43:00 2010 +++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Feb 12 03:55:04 2010
@@ -7639,7 +7639,7 @@
   switch (op_) {
     case Token::ADD: {
       // Test for string arguments before calling runtime.
-      Label not_strings, not_string1, string1;
+      Label not_strings, not_string1, string1, string1_smi2;
       Result answer;
       __ test(edx, Immediate(kSmiTagMask));
       __ j(zero, &not_string1);
@@ -7648,15 +7648,56 @@

       // First argument is a string, test second.
       __ test(eax, Immediate(kSmiTagMask));
-      __ j(zero, &string1);
+      __ j(zero, &string1_smi2);
       __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ecx);
       __ j(above_equal, &string1);

// First and second argument are strings. Jump to the string add stub.
-      StringAddStub stub(NO_STRING_CHECK_IN_STUB);
-      __ TailCallStub(&stub);
-
-      // Only first argument is a string.
+      StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB);
+      __ TailCallStub(&string_add_stub);
+
+      __ bind(&string1_smi2);
+ // First argument is a string, second is a smi. Try to lookup the number
+      // string for the smi in the number string cache.
+      // Load the number string cache.
+      ExternalReference roots_address = ExternalReference::roots_address();
+      __ mov(ecx, Immediate(Heap::kNumberStringCacheRootIndex));
+      __ mov(ebx,
+             Operand::StaticArray(ecx, times_pointer_size, roots_address));
+      // Make the hash mask from the length of the number string cache. It
+      // contains two elements (number and string) for each cache entry.
+      __ mov(ecx, FieldOperand(ebx, FixedArray::kLengthOffset));
+      __ shr(ecx, 1);  // Divide length by two (length is not a smi).
+      __ sub(Operand(ecx), 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(edi, eax);
+      __ SmiUntag(edi);
+      __ and_(edi, Operand(ecx));
+      // Check if the entry is the smi we are looking for.
+      __ cmp(eax,
+             FieldOperand(ebx,
+                          edi,
+                          times_twice_pointer_size,
+                          FixedArray::kHeaderSize));
+      __ IncrementCounter(equal, &Counters::string_plus_smi_hit, 1);
+      __ IncrementCounter(not_equal, &Counters::string_plus_smi_miss, 1);
+      __ j(not_equal, &string1);
+
+ // Get the string from the cache and call the string add stub to make the
+      // result.
+      __ mov(edi,
+             FieldOperand(ebx,
+                          edi,
+                          times_twice_pointer_size,
+                          FixedArray::kHeaderSize + kPointerSize));
+      __ EnterInternalFrame();
+      __ push(edx);  // Original first argument.
+      __ push(edi);  // Number to string result for second argument.
+      __ CallStub(&string_add_stub);
+      __ LeaveInternalFrame();
+      __ ret(2 * kPointerSize);
+
       __ bind(&string1);
       __ InvokeBuiltin(
           HasArgsReversed() ?
=======================================
--- /branches/bleeding_edge/src/v8-counters.h   Tue Feb  9 08:14:14 2010
+++ /branches/bleeding_edge/src/v8-counters.h   Fri Feb 12 03:55:04 2010
@@ -167,7 +167,9 @@
   SC(string_compare_native, V8.StringCompareNative)                   \
   SC(string_compare_runtime, V8.StringCompareRuntime)                 \
   SC(regexp_entry_runtime, V8.RegExpEntryRuntime)                     \
-  SC(regexp_entry_native, V8.RegExpEntryNative)
+  SC(regexp_entry_native, V8.RegExpEntryNative)                       \
+  SC(string_plus_smi_hit, V8.StringPlusSmiHit)                        \
+  SC(string_plus_smi_miss, V8.StringPlusSmiMiss)

 // This file contains all the v8 counters that are in use.
 class Counters : AllStatic {

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to