Revision: 7809
Author:   [email protected]
Date:     Fri May  6 07:19:51 2011
Log:      Extract common code in string compare loops.

Review URL: http://codereview.chromium.org/6927044
http://code.google.com/p/v8/source/detail?r=7809

Modified:
 /branches/bleeding_edge/src/arm/code-stubs-arm.cc
 /branches/bleeding_edge/src/arm/code-stubs-arm.h
 /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc
 /branches/bleeding_edge/src/ia32/code-stubs-ia32.h
 /branches/bleeding_edge/src/x64/code-stubs-x64.cc
 /branches/bleeding_edge/src/x64/code-stubs-x64.h

=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.cc Thu May 5 05:30:57 2011 +++ /branches/bleeding_edge/src/arm/code-stubs-arm.cc Fri May 6 07:19:51 2011
@@ -5430,27 +5430,9 @@

   // Compare characters.
   __ bind(&compare_chars);
-
-  // Change index to run from -length to -1 by adding length to string
-  // start. This means that loop ends when index reaches zero, which
-  // doesn't need an additional compare.
-  __ SmiUntag(length);
-  __ add(scratch2, length,
-         Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
-  __ add(left, left, Operand(scratch2));
-  __ add(right, right, Operand(scratch2));
-  __ rsb(length, length, Operand(0));
-  Register index = length;  // index = -length;
-
-  // Compare loop.
-  Label loop;
-  __ bind(&loop);
-  __ ldrb(scratch2, MemOperand(left, index));
-  __ ldrb(scratch3, MemOperand(right, index));
-  __ cmp(scratch2, scratch3);
-  __ b(ne, &strings_not_equal);
-  __ add(index, index, Operand(1), SetCC);
-  __ b(ne, &loop);
+  GenerateAsciiCharsCompareLoop(masm,
+                                left, right, length, scratch2, scratch3,
+                                &strings_not_equal);

   // Characters are equal.
   __ mov(r0, Operand(Smi::FromInt(EQUAL)));
@@ -5465,7 +5447,7 @@
                                                         Register scratch2,
                                                         Register scratch3,
Register scratch4) {
-  Label compare_lengths;
+  Label result_not_equal, compare_lengths;
   // Find minimum length and length difference.
   __ ldr(scratch1, FieldMemOperand(left, String::kLengthOffset));
   __ ldr(scratch2, FieldMemOperand(right, String::kLengthOffset));
@@ -5477,44 +5459,54 @@
   __ tst(min_length, Operand(min_length));
   __ b(eq, &compare_lengths);

-  // Untag smi.
-  __ mov(min_length, Operand(min_length, ASR, kSmiTagSize));
-
-  // Setup registers so that we only need to increment one register
-  // in the loop.
-  __ add(scratch2, min_length,
-         Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
-  __ add(left, left, Operand(scratch2));
-  __ add(right, right, Operand(scratch2));
- // Registers left and right points to the min_length character of strings.
-  __ rsb(min_length, min_length, Operand(-1));
-  Register index = min_length;
-  // Index starts at -min_length.
-
-  {
-    // Compare loop.
-    Label loop;
-    __ bind(&loop);
-    // Compare characters.
-    __ add(index, index, Operand(1), SetCC);
-    __ ldrb(scratch2, MemOperand(left, index), ne);
-    __ ldrb(scratch4, MemOperand(right, index), ne);
-    // Skip to compare lengths with eq condition true.
-    __ b(eq, &compare_lengths);
-    __ cmp(scratch2, scratch4);
-    __ b(eq, &loop);
-    // Fallthrough with eq condition false.
-  }
-  // Compare lengths -  strings up to min-length are equal.
+  // Compare loop.
+  GenerateAsciiCharsCompareLoop(masm,
+ left, right, min_length, scratch2, scratch4,
+                                &result_not_equal);
+
+  // Compare lengths - strings up to min-length are equal.
   __ bind(&compare_lengths);
   ASSERT(Smi::FromInt(EQUAL) == static_cast<Smi*>(0));
-  // Use zero length_delta as result.
-  __ mov(r0, Operand(length_delta), SetCC, eq);
-  // Fall through to here if characters compare not-equal.
+  // Use length_delta as result if it's zero.
+  __ mov(r0, Operand(length_delta), SetCC);
+  __ bind(&result_not_equal);
+  // Conditionally update the result based either on length_delta or
+  // the last comparion performed in the loop above.
   __ mov(r0, Operand(Smi::FromInt(GREATER)), LeaveCC, gt);
   __ mov(r0, Operand(Smi::FromInt(LESS)), LeaveCC, lt);
   __ Ret();
 }
+
+
+void StringCompareStub::GenerateAsciiCharsCompareLoop(
+    MacroAssembler* masm,
+    Register left,
+    Register right,
+    Register length,
+    Register scratch1,
+    Register scratch2,
+    Label* chars_not_equal) {
+  // Change index to run from -length to -1 by adding length to string
+  // start. This means that loop ends when index reaches zero, which
+  // doesn't need an additional compare.
+  __ SmiUntag(length);
+  __ add(scratch1, length,
+         Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
+  __ add(left, left, Operand(scratch1));
+  __ add(right, right, Operand(scratch1));
+  __ rsb(length, length, Operand(0));
+  Register index = length;  // index = -length;
+
+  // Compare loop.
+  Label loop;
+  __ bind(&loop);
+  __ ldrb(scratch1, MemOperand(left, index));
+  __ ldrb(scratch2, MemOperand(right, index));
+  __ cmp(scratch1, scratch2);
+  __ b(ne, chars_not_equal);
+  __ add(index, index, Operand(1), SetCC);
+  __ b(ne, &loop);
+}


 void StringCompareStub::Generate(MacroAssembler* masm) {
=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.h Thu May 5 05:30:57 2011 +++ /branches/bleeding_edge/src/arm/code-stubs-arm.h Fri May 6 07:19:51 2011
@@ -346,10 +346,17 @@
                                             Register scratch3);

  private:
-  Major MajorKey() { return StringCompare; }
-  int MinorKey() { return 0; }
-
-  void Generate(MacroAssembler* masm);
+  virtual Major MajorKey() { return StringCompare; }
+  virtual int MinorKey() { return 0; }
+  virtual void Generate(MacroAssembler* masm);
+
+  static void GenerateAsciiCharsCompareLoop(MacroAssembler* masm,
+                                            Register left,
+                                            Register right,
+                                            Register length,
+                                            Register scratch1,
+                                            Register scratch2,
+                                            Label* chars_not_equal);
 };


=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Thu May 5 05:30:57 2011 +++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Fri May 6 07:19:51 2011
@@ -5637,26 +5637,8 @@

   // Compare characters.
   __ bind(&compare_chars);
-
-  // Change index to run from -length to -1 by adding length to string
-  // start. This means that loop ends when index reaches zero, which
-  // doesn't need an additional compare.
-  __ SmiUntag(length);
-  __ lea(left,
-         FieldOperand(left, length, times_1, SeqAsciiString::kHeaderSize));
-  __ lea(right,
- FieldOperand(right, length, times_1, SeqAsciiString::kHeaderSize));
-  __ neg(length);
-  Register index = length;  // index = -length;
-
-  // Compare loop.
-  NearLabel loop;
-  __ bind(&loop);
-  __ mov_b(scratch2, Operand(left, index, times_1, 0));
-  __ cmpb(scratch2, Operand(right, index, times_1, 0));
-  __ j(not_equal, &strings_not_equal);
-  __ add(Operand(index), Immediate(1));
-  __ j(not_zero, &loop);
+  GenerateAsciiCharsCompareLoop(masm, left, right, length, scratch2,
+                                &strings_not_equal);

   // Characters are equal.
   __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
@@ -5670,10 +5652,6 @@
                                                         Register scratch1,
                                                         Register scratch2,
Register scratch3) {
-  Label result_not_equal;
-  Label result_greater;
-  Label compare_lengths;
-
   Counters* counters = masm->isolate()->counters();
   __ IncrementCounter(counters->string_compare_native(), 1);

@@ -5693,36 +5671,14 @@
   Register min_length = scratch1;

   // If either length is zero, just compare lengths.
+  NearLabel compare_lengths;
   __ test(min_length, Operand(min_length));
   __ j(zero, &compare_lengths);

-  // Change index to run from -min_length to -1 by adding min_length
-  // to string start. This means that loop ends when index reaches zero,
-  // which doesn't need an additional compare.
-  __ SmiUntag(min_length);
-  __ lea(left,
-         FieldOperand(left,
-                      min_length, times_1,
-                      SeqAsciiString::kHeaderSize));
-  __ lea(right,
-         FieldOperand(right,
-                      min_length, times_1,
-                      SeqAsciiString::kHeaderSize));
-  __ neg(min_length);
-
-  Register index = min_length;  // index = -min_length;
-
-  {
-    // Compare loop.
-    NearLabel loop;
-    __ bind(&loop);
-    // Compare characters.
-    __ mov_b(scratch2, Operand(left, index, times_1, 0));
-    __ cmpb(scratch2, Operand(right, index, times_1, 0));
-    __ j(not_equal, &result_not_equal);
-    __ add(Operand(index), Immediate(1));
-    __ j(not_zero, &loop);
-  }
+  // Compare characters.
+  NearLabel result_not_equal;
+  GenerateAsciiCharsCompareLoop(masm, left, right, min_length, scratch2,
+                                &result_not_equal);

   // Compare lengths -  strings up to min-length are equal.
   __ bind(&compare_lengths);
@@ -5735,6 +5691,7 @@
   __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
   __ ret(0);

+  NearLabel result_greater;
   __ bind(&result_not_equal);
   __ j(greater, &result_greater);

@@ -5747,6 +5704,35 @@
   __ Set(eax, Immediate(Smi::FromInt(GREATER)));
   __ ret(0);
 }
+
+
+void StringCompareStub::GenerateAsciiCharsCompareLoop(
+    MacroAssembler* masm,
+    Register left,
+    Register right,
+    Register length,
+    Register scratch,
+    NearLabel* chars_not_equal) {
+  // Change index to run from -length to -1 by adding length to string
+  // start. This means that loop ends when index reaches zero, which
+  // doesn't need an additional compare.
+  __ SmiUntag(length);
+  __ lea(left,
+         FieldOperand(left, length, times_1, SeqAsciiString::kHeaderSize));
+  __ lea(right,
+ FieldOperand(right, length, times_1, SeqAsciiString::kHeaderSize));
+  __ neg(length);
+  Register index = length;  // index = -length;
+
+  // Compare loop.
+  NearLabel loop;
+  __ bind(&loop);
+  __ mov_b(scratch, Operand(left, index, times_1, 0));
+  __ cmpb(scratch, Operand(right, index, times_1, 0));
+  __ j(not_equal, chars_not_equal);
+  __ add(Operand(index), Immediate(1));
+  __ j(not_zero, &loop);
+}


 void StringCompareStub::Generate(MacroAssembler* masm) {
=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.h Thu May 5 05:30:57 2011 +++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.h Fri May 6 07:19:51 2011
@@ -391,10 +391,16 @@
                                             Register scratch2);

  private:
-  Major MajorKey() { return StringCompare; }
-  int MinorKey() { return 0; }
-
-  void Generate(MacroAssembler* masm);
+  virtual Major MajorKey() { return StringCompare; }
+  virtual int MinorKey() { return 0; }
+  virtual void Generate(MacroAssembler* masm);
+
+  static void GenerateAsciiCharsCompareLoop(MacroAssembler* masm,
+                                            Register left,
+                                            Register right,
+                                            Register length,
+                                            Register scratch,
+                                            NearLabel* chars_not_equal);
 };


=======================================
--- /branches/bleeding_edge/src/x64/code-stubs-x64.cc Thu May 5 05:30:57 2011 +++ /branches/bleeding_edge/src/x64/code-stubs-x64.cc Fri May 6 07:19:51 2011
@@ -4523,26 +4523,9 @@

   // Compare characters.
   __ bind(&compare_chars);
-
-  // Change index to run from -length to -1 by adding length to string
-  // start. This means that loop ends when index reaches zero, which
-  // doesn't need an additional compare.
-  __ SmiToInteger32(length, length);
-  __ lea(left,
-         FieldOperand(left, length, times_1, SeqAsciiString::kHeaderSize));
-  __ lea(right,
- FieldOperand(right, length, times_1, SeqAsciiString::kHeaderSize));
-  __ neg(length);
-  Register index = length;  // index = -length;
-
-  // Compare loop.
-  NearLabel strings_not_equal, loop;
-  __ bind(&loop);
-  __ movb(scratch2, Operand(left, index, times_1, 0));
-  __ cmpb(scratch2, Operand(right, index, times_1, 0));
-  __ j(not_equal, &strings_not_equal);
-  __ addq(index, Immediate(1));
-  __ j(not_zero, &loop);
+  NearLabel strings_not_equal;
+  GenerateAsciiCharsCompareLoop(masm, left, right, length, scratch2,
+                                &strings_not_equal);

   // Characters are equal.
   __ Move(rax, Smi::FromInt(EQUAL));
@@ -4589,35 +4572,11 @@
   __ SmiTest(min_length);
   __ j(zero, &compare_lengths);

-  __ SmiToInteger32(min_length, min_length);
-
-  // Registers scratch2 and scratch3 are free.
+  // Compare loop.
   NearLabel result_not_equal;
-  Label loop;
-  {
-    // Check characters 0 .. min_length - 1 in a loop.
-    // Use scratch3 as loop index, min_length as limit and scratch2
-    // for computation.
-    const Register index = scratch3;
-    __ Set(index, 0);  // Index into strings.
-    __ bind(&loop);
-    // Compare characters.
-    // TODO(lrn): Could we load more than one character at a time?
-    __ movb(scratch2, FieldOperand(left,
-                                   index,
-                                   times_1,
-                                   SeqAsciiString::kHeaderSize));
-    // Increment index and use -1 modifier on next load to give
-    // the previous load extra time to complete.
-    __ addl(index, Immediate(1));
-    __ cmpb(scratch2, FieldOperand(right,
-                                   index,
-                                   times_1,
-                                   SeqAsciiString::kHeaderSize - 1));
-    __ j(not_equal, &result_not_equal);
-    __ cmpl(index, min_length);
-    __ j(not_equal, &loop);
-  }
+  GenerateAsciiCharsCompareLoop(masm, left, right, min_length, scratch2,
+                                &result_not_equal);
+
   // Completed loop without finding different characters.
   // Compare lengths (precomputed).
   __ bind(&compare_lengths);
@@ -4642,6 +4601,35 @@
   __ Move(rax, Smi::FromInt(GREATER));
   __ ret(0);
 }
+
+
+void StringCompareStub::GenerateAsciiCharsCompareLoop(
+    MacroAssembler* masm,
+    Register left,
+    Register right,
+    Register length,
+    Register scratch,
+    NearLabel* chars_not_equal) {
+  // Change index to run from -length to -1 by adding length to string
+  // start. This means that loop ends when index reaches zero, which
+  // doesn't need an additional compare.
+  __ SmiToInteger32(length, length);
+  __ lea(left,
+         FieldOperand(left, length, times_1, SeqAsciiString::kHeaderSize));
+  __ lea(right,
+ FieldOperand(right, length, times_1, SeqAsciiString::kHeaderSize));
+  __ neg(length);
+  Register index = length;  // index = -length;
+
+  // Compare loop.
+  NearLabel loop;
+  __ bind(&loop);
+  __ movb(scratch, Operand(left, index, times_1, 0));
+  __ cmpb(scratch, Operand(right, index, times_1, 0));
+  __ j(not_equal, chars_not_equal);
+  __ addq(index, Immediate(1));
+  __ j(not_zero, &loop);
+}


 void StringCompareStub::Generate(MacroAssembler* masm) {
=======================================
--- /branches/bleeding_edge/src/x64/code-stubs-x64.h Thu May 5 05:30:57 2011 +++ /branches/bleeding_edge/src/x64/code-stubs-x64.h Fri May 6 07:19:51 2011
@@ -384,10 +384,16 @@
                                             Register scratch2);

  private:
-  Major MajorKey() { return StringCompare; }
-  int MinorKey() { return 0; }
-
-  void Generate(MacroAssembler* masm);
+  virtual Major MajorKey() { return StringCompare; }
+  virtual int MinorKey() { return 0; }
+  virtual void Generate(MacroAssembler* masm);
+
+  static void GenerateAsciiCharsCompareLoop(MacroAssembler* masm,
+                                            Register left,
+                                            Register right,
+                                            Register length,
+                                            Register scratch,
+                                            NearLabel* chars_not_equal);
 };


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

Reply via email to