Use direct loop when filling small arrays.
authorantonm@chromium.org <antonm@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 17 May 2010 14:14:34 +0000 (14:14 +0000)
committerantonm@chromium.org <antonm@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 17 May 2010 14:14:34 +0000 (14:14 +0000)
r3995 (http://code.google.com/p/v8/source/detail?r=3995) introduce performance
regression for the case when arrat size is small (think new Array(4)).

It turns out that in those cases rep stos is slower than plain loop (apprently
due to ecx increment, but I didn't check this hypothesis.)  The next thing
to try could be direct jump into right place of long sequence of stos'es.

Review URL: http://codereview.chromium.org/2082006

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4664 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/ia32/assembler-ia32.cc
src/ia32/assembler-ia32.h
src/ia32/builtins-ia32.cc
src/ia32/disasm-ia32.cc
test/cctest/test-disasm-ia32.cc

index 19895d0..0d3f01d 100644 (file)
@@ -776,6 +776,13 @@ void Assembler::rep_stos() {
 }
 
 
+void Assembler::stos() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xAB);
+}
+
+
 void Assembler::xchg(Register dst, Register src) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
index 6a7effd..8620c93 100644 (file)
@@ -551,6 +551,7 @@ class Assembler : public Malloced {
   // Repetitive string instructions.
   void rep_movs();
   void rep_stos();
+  void stos();
 
   // Exchange two registers
   void xchg(Register dst, Register src);
index 2db21d5..030688a 100644 (file)
@@ -806,6 +806,7 @@ static void AllocateJSArray(MacroAssembler* masm,
                             Label* gc_required) {
   ASSERT(scratch.is(edi));  // rep stos destination
   ASSERT(!fill_with_hole || array_size.is(ecx));  // rep stos count
+  ASSERT(!fill_with_hole || !result.is(eax));  // result is never eax
 
   // Load the initial map from the array function.
   __ mov(elements_array,
@@ -863,15 +864,22 @@ static void AllocateJSArray(MacroAssembler* masm,
   if (fill_with_hole) {
     __ lea(edi, Operand(elements_array,
                         FixedArray::kHeaderSize - kHeapObjectTag));
-
-    __ push(eax);
     __ mov(eax, Factory::the_hole_value());
-
     __ cld();
+    // Do not use rep stos when filling less than kRepStosThreshold
+    // words.
+    const int kRepStosThreshold = 16;
+    Label loop, entry, done;
+    __ cmp(ecx, kRepStosThreshold);
+    __ j(below, &loop);  // Note: ecx > 0.
     __ rep_stos();
-
-    // Restore saved registers.
-    __ pop(eax);
+    __ jmp(&done);
+    __ bind(&loop);
+    __ stos();
+    __ bind(&entry);
+    __ cmp(edi, Operand(elements_array_end));
+    __ j(below, &loop);
+    __ bind(&done);
   }
 }
 
@@ -970,13 +978,14 @@ static void ArrayNativeCode(MacroAssembler* masm,
   AllocateJSArray(masm,
                   edi,
                   ecx,
-                  eax,
                   ebx,
+                  eax,
                   edx,
                   edi,
                   true,
                   &prepare_generic_code_call);
   __ IncrementCounter(&Counters::array_function_native, 1);
+  __ mov(eax, ebx);
   __ pop(ebx);
   if (construct_call) {
     __ pop(edi);
index 8d342e0..06c62ec 100644 (file)
@@ -90,6 +90,7 @@ static ByteMnemonic zero_operands_instr[] = {
   {0x99, "cdq", UNSET_OP_ORDER},
   {0x9B, "fwait", UNSET_OP_ORDER},
   {0xFC, "cld", UNSET_OP_ORDER},
+  {0xAB, "stos", UNSET_OP_ORDER},
   {-1, "", UNSET_OP_ORDER}
 };
 
index 02e64b4..f94cd45 100644 (file)
@@ -237,6 +237,7 @@ TEST(DisasmIa320) {
   __ cld();
   __ rep_movs();
   __ rep_stos();
+  __ stos();
 
   __ sub(edx, Operand(ebx, ecx, times_4, 10000));
   __ sub(edx, Operand(ebx));