From: vitalyr@chromium.org Date: Fri, 6 May 2011 14:19:51 +0000 (+0000) Subject: Extract common code in string compare loops. X-Git-Tag: upstream/4.7.83~19474 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=913ce07e2ff3fadfdcac696a5697c2870df9ebbe;p=platform%2Fupstream%2Fv8.git Extract common code in string compare loops. Review URL: http://codereview.chromium.org/6927044 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7809 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc index caeb6c11f..10340b0db 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc @@ -5430,27 +5430,9 @@ void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm, // 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 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, 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,46 +5459,56 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, __ 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. + GenerateAsciiCharsCompareLoop(masm, + left, right, min_length, scratch2, scratch4, + &result_not_equal); - { - // 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 lengths - strings up to min-length are equal. __ bind(&compare_lengths); ASSERT(Smi::FromInt(EQUAL) == static_cast(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) { Label runtime; diff --git a/src/arm/code-stubs-arm.h b/src/arm/code-stubs-arm.h index a167c0304..112503f78 100644 --- a/src/arm/code-stubs-arm.h +++ b/src/arm/code-stubs-arm.h @@ -346,10 +346,17 @@ class StringCompareStub: public CodeStub { Register scratch3); private: - Major MajorKey() { return StringCompare; } - int MinorKey() { return 0; } + virtual Major MajorKey() { return StringCompare; } + virtual int MinorKey() { return 0; } + virtual void Generate(MacroAssembler* masm); - void Generate(MacroAssembler* masm); + static void GenerateAsciiCharsCompareLoop(MacroAssembler* masm, + Register left, + Register right, + Register length, + Register scratch1, + Register scratch2, + Label* chars_not_equal); }; diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc index 0392e1da7..00fab7f55 100644 --- a/src/ia32/code-stubs-ia32.cc +++ b/src/ia32/code-stubs-ia32.cc @@ -5637,26 +5637,8 @@ void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm, // 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 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, 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 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, 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 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, __ Set(eax, Immediate(Smi::FromInt(EQUAL))); __ ret(0); + NearLabel result_greater; __ bind(&result_not_equal); __ j(greater, &result_greater); @@ -5749,6 +5706,35 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, } +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) { Label runtime; diff --git a/src/ia32/code-stubs-ia32.h b/src/ia32/code-stubs-ia32.h index 1132cb4d4..768bfea9a 100644 --- a/src/ia32/code-stubs-ia32.h +++ b/src/ia32/code-stubs-ia32.h @@ -391,10 +391,16 @@ class StringCompareStub: public CodeStub { Register scratch2); private: - Major MajorKey() { return StringCompare; } - int MinorKey() { return 0; } + virtual Major MajorKey() { return StringCompare; } + virtual int MinorKey() { return 0; } + virtual void Generate(MacroAssembler* masm); - void Generate(MacroAssembler* masm); + static void GenerateAsciiCharsCompareLoop(MacroAssembler* masm, + Register left, + Register right, + Register length, + Register scratch, + NearLabel* chars_not_equal); }; diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc index cfe62e72f..5f0a84d7d 100644 --- a/src/x64/code-stubs-x64.cc +++ b/src/x64/code-stubs-x64.cc @@ -4523,26 +4523,9 @@ void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm, // 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 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, __ 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); @@ -4644,6 +4603,35 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, } +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) { Label runtime; diff --git a/src/x64/code-stubs-x64.h b/src/x64/code-stubs-x64.h index f1e1e5b49..44e277591 100644 --- a/src/x64/code-stubs-x64.h +++ b/src/x64/code-stubs-x64.h @@ -384,10 +384,16 @@ class StringCompareStub: public CodeStub { Register scratch2); private: - Major MajorKey() { return StringCompare; } - int MinorKey() { return 0; } + virtual Major MajorKey() { return StringCompare; } + virtual int MinorKey() { return 0; } + virtual void Generate(MacroAssembler* masm); - void Generate(MacroAssembler* masm); + static void GenerateAsciiCharsCompareLoop(MacroAssembler* masm, + Register left, + Register right, + Register length, + Register scratch, + NearLabel* chars_not_equal); };