Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(204)

Side by Side Diff: src/ia32/codegen-ia32.cc

Issue 546087: Implement inline string compare on ARM. (Closed)
Patch Set: Further optimization of ARM version Created 10 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/ia32/assembler-ia32.cc ('k') | src/ia32/disasm-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 8557 matching lines...) Expand 10 before | Expand all | Expand 10 after
8568 BranchIfNonSymbol(masm, &check_for_strings, edx, ecx); 8568 BranchIfNonSymbol(masm, &check_for_strings, edx, ecx);
8569 8569
8570 // We've already checked for object identity, so if both operands 8570 // We've already checked for object identity, so if both operands
8571 // are symbols they aren't equal. Register eax already holds a 8571 // are symbols they aren't equal. Register eax already holds a
8572 // non-zero value, which indicates not equal, so just return. 8572 // non-zero value, which indicates not equal, so just return.
8573 __ ret(2 * kPointerSize); 8573 __ ret(2 * kPointerSize);
8574 } 8574 }
8575 8575
8576 __ bind(&check_for_strings); 8576 __ bind(&check_for_strings);
8577 8577
8578 // Check that both objects are not smis. 8578 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &call_builtin);
8579 ASSERT_EQ(0, kSmiTag);
8580 __ mov(ebx, Operand(edx));
8581 __ and_(ebx, Operand(eax));
8582 __ test(ebx, Immediate(kSmiTagMask));
8583 __ j(zero, &call_builtin);
8584
8585 // Load instance type for both objects.
8586 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
8587 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
8588 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
8589 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
8590
8591 // Check that both are flat ascii strings.
8592 Label non_ascii_flat;
8593 ASSERT(kNotStringTag != 0);
8594 const int kFlatAsciiString =
8595 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
8596 __ and_(ecx, kFlatAsciiString);
8597 __ cmp(ecx, kStringTag | kSeqStringTag | kAsciiStringTag);
8598 __ j(not_equal, &call_builtin);
8599 __ and_(ebx, kFlatAsciiString);
8600 __ cmp(ebx, kStringTag | kSeqStringTag | kAsciiStringTag);
8601 __ j(not_equal, &call_builtin);
8602 8579
8603 // Inline comparison of ascii strings. 8580 // Inline comparison of ascii strings.
8604 StringCompareStub::GenerateCompareFlatAsciiStrings(masm, 8581 StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
8605 edx, 8582 edx,
8606 eax, 8583 eax,
8607 ecx, 8584 ecx,
8608 ebx, 8585 ebx,
8609 edi); 8586 edi);
8610 #ifdef DEBUG 8587 #ifdef DEBUG
8611 __ Abort("Unexpected fall-through from string comparison"); 8588 __ Abort("Unexpected fall-through from string comparison");
(...skipping 1033 matching lines...) Expand 10 before | Expand all | Expand 10 after
9645 __ TailCallRuntime(ExternalReference(Runtime::kSubString), 3, 1); 9622 __ TailCallRuntime(ExternalReference(Runtime::kSubString), 3, 1);
9646 } 9623 }
9647 9624
9648 9625
9649 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, 9626 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
9650 Register left, 9627 Register left,
9651 Register right, 9628 Register right,
9652 Register scratch1, 9629 Register scratch1,
9653 Register scratch2, 9630 Register scratch2,
9654 Register scratch3) { 9631 Register scratch3) {
9655 Label compare_lengths, compare_lengths_1; 9632 Label result_not_equal;
9633 Label result_greater;
9634 Label compare_lengths;
9635 // Find minimum length.
9636 Label left_shorter;
9637 __ mov(scratch1, FieldOperand(left, String::kLengthOffset));
9638 __ mov(scratch3, scratch1);
9639 __ sub(scratch3, FieldOperand(right, String::kLengthOffset));
9656 9640
9657 // Find minimum length. If either length is zero just compare lengths. 9641 Register length_delta = scratch3;
9658 __ mov(scratch1, FieldOperand(left, String::kLengthOffset)); 9642
9659 __ test(scratch1, Operand(scratch1)); 9643 __ j(less_equal, &left_shorter);
9660 __ j(zero, &compare_lengths_1); 9644 // Right string is shorter. Change scratch1 to be length of right string.
9661 __ mov(scratch2, FieldOperand(right, String::kLengthOffset)); 9645 __ sub(scratch1, Operand(length_delta));
9662 __ test(scratch2, Operand(scratch2)); 9646 __ bind(&left_shorter);
9663 __ j(zero, &compare_lengths_1); 9647
9664 __ cmp(scratch1, Operand(scratch2)); 9648 Register min_length = scratch1;
9665 if (CpuFeatures::IsSupported(CMOV)) { 9649
9666 CpuFeatures::Scope use_cmov(CMOV); 9650 // If either length is zero, just compare lengths.
9667 __ cmov(greater, scratch1, Operand(scratch2)); 9651 __ test(min_length, Operand(min_length));
9668 } else { 9652 __ j(zero, &compare_lengths);
9669 Label l; 9653
9670 __ j(less, &l); 9654 // Change index to run from -min_length to -1 by adding min_length
9671 __ mov(scratch1, scratch2); 9655 // to string start. This means that loop ends when index reaches zero,
9672 __ bind(&l); 9656 // which doesn't need an additional compare.
9657 __ lea(left,
9658 FieldOperand(left,
9659 min_length, times_1,
9660 SeqAsciiString::kHeaderSize));
9661 __ lea(right,
9662 FieldOperand(right,
9663 min_length, times_1,
9664 SeqAsciiString::kHeaderSize));
9665 __ neg(min_length);
9666
9667 Register index = min_length; // index = -min_length;
9668
9669 {
9670 // Compare loop.
9671 Label loop;
9672 __ bind(&loop);
9673 // Compare characters.
9674 __ mov_b(scratch2, Operand(left, index, times_1, 0));
9675 __ cmpb(scratch2, Operand(right, index, times_1, 0));
9676 __ j(not_equal, &result_not_equal);
9677 __ add(Operand(index), Immediate(1));
9678 __ j(not_zero, &loop);
9673 } 9679 }
9674 9680
9675 Label result_greater, result_less; 9681 // Compare lengths - strings up to min-length are equal.
9676 Label loop;
9677 // Compare next character.
9678 __ mov(scratch3, Immediate(-1)); // Index into strings.
9679 __ bind(&loop);
9680 // Compare characters.
9681 Label character_compare_done;
9682 __ add(Operand(scratch3), Immediate(1));
9683 __ mov_b(scratch2, Operand(left,
9684 scratch3,
9685 times_1,
9686 SeqAsciiString::kHeaderSize - kHeapObjectTag));
9687 __ subb(scratch2, Operand(right,
9688 scratch3,
9689 times_1,
9690 SeqAsciiString::kHeaderSize - kHeapObjectTag));
9691 __ j(not_equal, &character_compare_done);
9692 __ sub(Operand(scratch1), Immediate(1));
9693 __ j(not_zero, &loop);
9694 // If min length characters match compare lengths otherwise last character
9695 // compare is the result.
9696 __ bind(&character_compare_done);
9697 __ j(equal, &compare_lengths);
9698 __ j(less, &result_less);
9699 __ jmp(&result_greater);
9700
9701 // Compare lengths.
9702 Label result_not_equal;
9703 __ bind(&compare_lengths); 9682 __ bind(&compare_lengths);
9704 __ mov(scratch1, FieldOperand(left, String::kLengthOffset)); 9683 __ test(length_delta, Operand(length_delta));
9705 __ bind(&compare_lengths_1);
9706 __ sub(scratch1, FieldOperand(right, String::kLengthOffset));
9707 __ j(not_zero, &result_not_equal); 9684 __ j(not_zero, &result_not_equal);
9708 9685
9709 // Result is EQUAL. 9686 // Result is EQUAL.
9710 ASSERT_EQ(0, EQUAL); 9687 ASSERT_EQ(0, EQUAL);
9711 ASSERT_EQ(0, kSmiTag); 9688 ASSERT_EQ(0, kSmiTag);
9712 __ xor_(eax, Operand(eax)); 9689 __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
9713 __ IncrementCounter(&Counters::string_compare_native, 1);
9714 __ ret(2 * kPointerSize); 9690 __ ret(2 * kPointerSize);
9691
9715 __ bind(&result_not_equal); 9692 __ bind(&result_not_equal);
9716 __ j(greater, &result_greater); 9693 __ j(greater, &result_greater);
9717 9694
9718 // Result is LESS. 9695 // Result is LESS.
9719 __ bind(&result_less); 9696 __ Set(eax, Immediate(Smi::FromInt(LESS)));
9720 __ mov(eax, Immediate(Smi::FromInt(LESS)->value()));
9721 __ IncrementCounter(&Counters::string_compare_native, 1);
9722 __ ret(2 * kPointerSize); 9697 __ ret(2 * kPointerSize);
9723 9698
9724 // Result is GREATER. 9699 // Result is GREATER.
9725 __ bind(&result_greater); 9700 __ bind(&result_greater);
9726 __ mov(eax, Immediate(Smi::FromInt(GREATER)->value())); 9701 __ Set(eax, Immediate(Smi::FromInt(GREATER)));
9727 __ IncrementCounter(&Counters::string_compare_native, 1);
9728 __ ret(2 * kPointerSize); 9702 __ ret(2 * kPointerSize);
9729 } 9703 }
9730 9704
9731 9705
9732 void StringCompareStub::Generate(MacroAssembler* masm) { 9706 void StringCompareStub::Generate(MacroAssembler* masm) {
9733 Label runtime; 9707 Label runtime;
9734 9708
9735 // Stack frame on entry. 9709 // Stack frame on entry.
9736 // esp[0]: return address 9710 // esp[0]: return address
9737 // esp[4]: right string 9711 // esp[4]: right string
9738 // esp[8]: left string 9712 // esp[8]: left string
9739 9713
9740 __ mov(edx, Operand(esp, 2 * kPointerSize)); // left 9714 __ mov(edx, Operand(esp, 2 * kPointerSize)); // left
9741 __ mov(eax, Operand(esp, 1 * kPointerSize)); // right 9715 __ mov(eax, Operand(esp, 1 * kPointerSize)); // right
9742 9716
9743 Label not_same; 9717 Label not_same;
9744 __ cmp(edx, Operand(eax)); 9718 __ cmp(edx, Operand(eax));
9745 __ j(not_equal, &not_same); 9719 __ j(not_equal, &not_same);
9746 ASSERT_EQ(0, EQUAL); 9720 ASSERT_EQ(0, EQUAL);
9747 ASSERT_EQ(0, kSmiTag); 9721 ASSERT_EQ(0, kSmiTag);
9748 __ xor_(eax, Operand(eax)); 9722 __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
9749 __ IncrementCounter(&Counters::string_compare_native, 1); 9723 __ IncrementCounter(&Counters::string_compare_native, 1);
9750 __ ret(2 * kPointerSize); 9724 __ ret(2 * kPointerSize);
9751 9725
9752 __ bind(&not_same); 9726 __ bind(&not_same);
9753 9727
9754 // Check that both objects are not smis. 9728 // Check that both objects are sequential ascii strings.
9755 ASSERT_EQ(0, kSmiTag); 9729 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &runtime);
9756 __ mov(ebx, Operand(edx));
9757 __ and_(ebx, Operand(eax));
9758 __ test(ebx, Immediate(kSmiTagMask));
9759 __ j(zero, &runtime);
9760
9761 // Load instance type for both strings.
9762 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
9763 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
9764 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
9765 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
9766
9767 // Check that both are flat ascii strings.
9768 Label non_ascii_flat;
9769 __ and_(ecx, kStringRepresentationMask | kStringEncodingMask);
9770 __ cmp(ecx, kSeqStringTag | kAsciiStringTag);
9771 __ j(not_equal, &non_ascii_flat);
9772 const int kFlatAsciiString =
9773 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
9774 __ and_(ebx, kFlatAsciiString);
9775 __ cmp(ebx, kStringTag | kSeqStringTag | kAsciiStringTag);
9776 __ j(not_equal, &non_ascii_flat);
9777 9730
9778 // Compare flat ascii strings. 9731 // Compare flat ascii strings.
9732 __ IncrementCounter(&Counters::string_compare_native, 1);
9779 GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi); 9733 GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi);
9780 9734
9781 __ bind(&non_ascii_flat);
9782
9783 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 9735 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
9784 // tagged as a small integer. 9736 // tagged as a small integer.
9785 __ bind(&runtime); 9737 __ bind(&runtime);
9786 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); 9738 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1);
9787 } 9739 }
9788 9740
9789 #undef __ 9741 #undef __
9790 9742
9791 } } // namespace v8::internal 9743 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/assembler-ia32.cc ('k') | src/ia32/disasm-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698