OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 5619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5630 NearLabel compare_chars; | 5630 NearLabel compare_chars; |
5631 __ bind(&check_zero_length); | 5631 __ bind(&check_zero_length); |
5632 STATIC_ASSERT(kSmiTag == 0); | 5632 STATIC_ASSERT(kSmiTag == 0); |
5633 __ test(length, Operand(length)); | 5633 __ test(length, Operand(length)); |
5634 __ j(not_zero, &compare_chars); | 5634 __ j(not_zero, &compare_chars); |
5635 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); | 5635 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
5636 __ ret(0); | 5636 __ ret(0); |
5637 | 5637 |
5638 // Compare characters. | 5638 // Compare characters. |
5639 __ bind(&compare_chars); | 5639 __ bind(&compare_chars); |
5640 | 5640 GenerateAsciiCharsCompareLoop(masm, left, right, length, scratch2, |
5641 // Change index to run from -length to -1 by adding length to string | 5641 &strings_not_equal); |
5642 // start. This means that loop ends when index reaches zero, which | |
5643 // doesn't need an additional compare. | |
5644 __ SmiUntag(length); | |
5645 __ lea(left, | |
5646 FieldOperand(left, length, times_1, SeqAsciiString::kHeaderSize)); | |
5647 __ lea(right, | |
5648 FieldOperand(right, length, times_1, SeqAsciiString::kHeaderSize)); | |
5649 __ neg(length); | |
5650 Register index = length; // index = -length; | |
5651 | |
5652 // Compare loop. | |
5653 NearLabel loop; | |
5654 __ bind(&loop); | |
5655 __ mov_b(scratch2, Operand(left, index, times_1, 0)); | |
5656 __ cmpb(scratch2, Operand(right, index, times_1, 0)); | |
5657 __ j(not_equal, &strings_not_equal); | |
5658 __ add(Operand(index), Immediate(1)); | |
5659 __ j(not_zero, &loop); | |
5660 | 5642 |
5661 // Characters are equal. | 5643 // Characters are equal. |
5662 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); | 5644 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
5663 __ ret(0); | 5645 __ ret(0); |
5664 } | 5646 } |
5665 | 5647 |
5666 | 5648 |
5667 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, | 5649 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, |
5668 Register left, | 5650 Register left, |
5669 Register right, | 5651 Register right, |
5670 Register scratch1, | 5652 Register scratch1, |
5671 Register scratch2, | 5653 Register scratch2, |
5672 Register scratch3) { | 5654 Register scratch3) { |
5673 Label result_not_equal; | |
5674 Label result_greater; | |
5675 Label compare_lengths; | |
5676 | |
5677 Counters* counters = masm->isolate()->counters(); | 5655 Counters* counters = masm->isolate()->counters(); |
5678 __ IncrementCounter(counters->string_compare_native(), 1); | 5656 __ IncrementCounter(counters->string_compare_native(), 1); |
5679 | 5657 |
5680 // Find minimum length. | 5658 // Find minimum length. |
5681 NearLabel left_shorter; | 5659 NearLabel left_shorter; |
5682 __ mov(scratch1, FieldOperand(left, String::kLengthOffset)); | 5660 __ mov(scratch1, FieldOperand(left, String::kLengthOffset)); |
5683 __ mov(scratch3, scratch1); | 5661 __ mov(scratch3, scratch1); |
5684 __ sub(scratch3, FieldOperand(right, String::kLengthOffset)); | 5662 __ sub(scratch3, FieldOperand(right, String::kLengthOffset)); |
5685 | 5663 |
5686 Register length_delta = scratch3; | 5664 Register length_delta = scratch3; |
5687 | 5665 |
5688 __ j(less_equal, &left_shorter); | 5666 __ j(less_equal, &left_shorter); |
5689 // Right string is shorter. Change scratch1 to be length of right string. | 5667 // Right string is shorter. Change scratch1 to be length of right string. |
5690 __ sub(scratch1, Operand(length_delta)); | 5668 __ sub(scratch1, Operand(length_delta)); |
5691 __ bind(&left_shorter); | 5669 __ bind(&left_shorter); |
5692 | 5670 |
5693 Register min_length = scratch1; | 5671 Register min_length = scratch1; |
5694 | 5672 |
5695 // If either length is zero, just compare lengths. | 5673 // If either length is zero, just compare lengths. |
| 5674 NearLabel compare_lengths; |
5696 __ test(min_length, Operand(min_length)); | 5675 __ test(min_length, Operand(min_length)); |
5697 __ j(zero, &compare_lengths); | 5676 __ j(zero, &compare_lengths); |
5698 | 5677 |
5699 // Change index to run from -min_length to -1 by adding min_length | 5678 // Compare characters. |
5700 // to string start. This means that loop ends when index reaches zero, | 5679 NearLabel result_not_equal; |
5701 // which doesn't need an additional compare. | 5680 GenerateAsciiCharsCompareLoop(masm, left, right, min_length, scratch2, |
5702 __ SmiUntag(min_length); | 5681 &result_not_equal); |
5703 __ lea(left, | |
5704 FieldOperand(left, | |
5705 min_length, times_1, | |
5706 SeqAsciiString::kHeaderSize)); | |
5707 __ lea(right, | |
5708 FieldOperand(right, | |
5709 min_length, times_1, | |
5710 SeqAsciiString::kHeaderSize)); | |
5711 __ neg(min_length); | |
5712 | |
5713 Register index = min_length; // index = -min_length; | |
5714 | |
5715 { | |
5716 // Compare loop. | |
5717 NearLabel loop; | |
5718 __ bind(&loop); | |
5719 // Compare characters. | |
5720 __ mov_b(scratch2, Operand(left, index, times_1, 0)); | |
5721 __ cmpb(scratch2, Operand(right, index, times_1, 0)); | |
5722 __ j(not_equal, &result_not_equal); | |
5723 __ add(Operand(index), Immediate(1)); | |
5724 __ j(not_zero, &loop); | |
5725 } | |
5726 | 5682 |
5727 // Compare lengths - strings up to min-length are equal. | 5683 // Compare lengths - strings up to min-length are equal. |
5728 __ bind(&compare_lengths); | 5684 __ bind(&compare_lengths); |
5729 __ test(length_delta, Operand(length_delta)); | 5685 __ test(length_delta, Operand(length_delta)); |
5730 __ j(not_zero, &result_not_equal); | 5686 __ j(not_zero, &result_not_equal); |
5731 | 5687 |
5732 // Result is EQUAL. | 5688 // Result is EQUAL. |
5733 STATIC_ASSERT(EQUAL == 0); | 5689 STATIC_ASSERT(EQUAL == 0); |
5734 STATIC_ASSERT(kSmiTag == 0); | 5690 STATIC_ASSERT(kSmiTag == 0); |
5735 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); | 5691 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
5736 __ ret(0); | 5692 __ ret(0); |
5737 | 5693 |
| 5694 NearLabel result_greater; |
5738 __ bind(&result_not_equal); | 5695 __ bind(&result_not_equal); |
5739 __ j(greater, &result_greater); | 5696 __ j(greater, &result_greater); |
5740 | 5697 |
5741 // Result is LESS. | 5698 // Result is LESS. |
5742 __ Set(eax, Immediate(Smi::FromInt(LESS))); | 5699 __ Set(eax, Immediate(Smi::FromInt(LESS))); |
5743 __ ret(0); | 5700 __ ret(0); |
5744 | 5701 |
5745 // Result is GREATER. | 5702 // Result is GREATER. |
5746 __ bind(&result_greater); | 5703 __ bind(&result_greater); |
5747 __ Set(eax, Immediate(Smi::FromInt(GREATER))); | 5704 __ Set(eax, Immediate(Smi::FromInt(GREATER))); |
5748 __ ret(0); | 5705 __ ret(0); |
5749 } | 5706 } |
5750 | 5707 |
5751 | 5708 |
| 5709 void StringCompareStub::GenerateAsciiCharsCompareLoop( |
| 5710 MacroAssembler* masm, |
| 5711 Register left, |
| 5712 Register right, |
| 5713 Register length, |
| 5714 Register scratch, |
| 5715 NearLabel* chars_not_equal) { |
| 5716 // Change index to run from -length to -1 by adding length to string |
| 5717 // start. This means that loop ends when index reaches zero, which |
| 5718 // doesn't need an additional compare. |
| 5719 __ SmiUntag(length); |
| 5720 __ lea(left, |
| 5721 FieldOperand(left, length, times_1, SeqAsciiString::kHeaderSize)); |
| 5722 __ lea(right, |
| 5723 FieldOperand(right, length, times_1, SeqAsciiString::kHeaderSize)); |
| 5724 __ neg(length); |
| 5725 Register index = length; // index = -length; |
| 5726 |
| 5727 // Compare loop. |
| 5728 NearLabel loop; |
| 5729 __ bind(&loop); |
| 5730 __ mov_b(scratch, Operand(left, index, times_1, 0)); |
| 5731 __ cmpb(scratch, Operand(right, index, times_1, 0)); |
| 5732 __ j(not_equal, chars_not_equal); |
| 5733 __ add(Operand(index), Immediate(1)); |
| 5734 __ j(not_zero, &loop); |
| 5735 } |
| 5736 |
| 5737 |
5752 void StringCompareStub::Generate(MacroAssembler* masm) { | 5738 void StringCompareStub::Generate(MacroAssembler* masm) { |
5753 Label runtime; | 5739 Label runtime; |
5754 | 5740 |
5755 // Stack frame on entry. | 5741 // Stack frame on entry. |
5756 // esp[0]: return address | 5742 // esp[0]: return address |
5757 // esp[4]: right string | 5743 // esp[4]: right string |
5758 // esp[8]: left string | 5744 // esp[8]: left string |
5759 | 5745 |
5760 __ mov(edx, Operand(esp, 2 * kPointerSize)); // left | 5746 __ mov(edx, Operand(esp, 2 * kPointerSize)); // left |
5761 __ mov(eax, Operand(esp, 1 * kPointerSize)); // right | 5747 __ mov(eax, Operand(esp, 1 * kPointerSize)); // right |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5996 // Do a tail call to the rewritten stub. | 5982 // Do a tail call to the rewritten stub. |
5997 __ jmp(Operand(edi)); | 5983 __ jmp(Operand(edi)); |
5998 } | 5984 } |
5999 | 5985 |
6000 | 5986 |
6001 #undef __ | 5987 #undef __ |
6002 | 5988 |
6003 } } // namespace v8::internal | 5989 } } // namespace v8::internal |
6004 | 5990 |
6005 #endif // V8_TARGET_ARCH_IA32 | 5991 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |