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

Side by Side Diff: src/x64/code-stubs-x64.cc

Issue 6928020: Faster string equals in generated code. (Closed)
Patch Set: Created 9 years, 7 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
« src/ia32/code-stubs-ia32.cc ('K') | « src/x64/code-stubs-x64.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 2817 matching lines...) Expand 10 before | Expand all | Expand 10 after
2828 // non-zero value, which indicates not equal, so just return. 2828 // non-zero value, which indicates not equal, so just return.
2829 __ ret(0); 2829 __ ret(0);
2830 } 2830 }
2831 2831
2832 __ bind(&check_for_strings); 2832 __ bind(&check_for_strings);
2833 2833
2834 __ JumpIfNotBothSequentialAsciiStrings( 2834 __ JumpIfNotBothSequentialAsciiStrings(
2835 rdx, rax, rcx, rbx, &check_unequal_objects); 2835 rdx, rax, rcx, rbx, &check_unequal_objects);
2836 2836
2837 // Inline comparison of ascii strings. 2837 // Inline comparison of ascii strings.
2838 StringCompareStub::GenerateCompareFlatAsciiStrings(masm, 2838 if (cc_ == equal) {
2839 StringCompareStub::GenerateFlatAsciiStringEquals(masm,
2839 rdx, 2840 rdx,
2840 rax, 2841 rax,
2841 rcx, 2842 rcx,
2842 rbx, 2843 rbx);
2843 rdi, 2844 } else {
2844 r8); 2845 StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
2846 rdx,
2847 rax,
2848 rcx,
2849 rbx,
2850 rdi,
2851 r8);
2852 }
2845 2853
2846 #ifdef DEBUG 2854 #ifdef DEBUG
2847 __ Abort("Unexpected fall-through from string comparison"); 2855 __ Abort("Unexpected fall-through from string comparison");
2848 #endif 2856 #endif
2849 2857
2850 __ bind(&check_unequal_objects); 2858 __ bind(&check_unequal_objects);
2851 if (cc_ == equal && !strict_) { 2859 if (cc_ == equal && !strict_) {
2852 // Not strict equality. Objects are unequal if 2860 // Not strict equality. Objects are unequal if
2853 // they are both JSObjects and not undetectable, 2861 // they are both JSObjects and not undetectable,
2854 // and their pointers are different. 2862 // and their pointers are different.
(...skipping 1627 matching lines...) Expand 10 before | Expand all | Expand 10 after
4482 __ bind(&return_rax); 4490 __ bind(&return_rax);
4483 __ IncrementCounter(counters->sub_string_native(), 1); 4491 __ IncrementCounter(counters->sub_string_native(), 1);
4484 __ ret(kArgumentsSize); 4492 __ ret(kArgumentsSize);
4485 4493
4486 // Just jump to runtime to create the sub string. 4494 // Just jump to runtime to create the sub string.
4487 __ bind(&runtime); 4495 __ bind(&runtime);
4488 __ TailCallRuntime(Runtime::kSubString, 3, 1); 4496 __ TailCallRuntime(Runtime::kSubString, 3, 1);
4489 } 4497 }
4490 4498
4491 4499
4500 void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm,
4501 Register left,
4502 Register right,
4503 Register scratch1,
4504 Register scratch2) {
4505 Register length = scratch1;
4506
4507 // Compare lengths.
4508 NearLabel check_zero_length;
4509 __ movq(length, FieldOperand(left, String::kLengthOffset));
4510 __ SmiCompare(length, FieldOperand(right, String::kLengthOffset));
4511 __ j(equal, &check_zero_length);
4512 __ Move(rax, Smi::FromInt(NOT_EQUAL));
4513 __ ret(0);
4514
4515 // Check if the length is zero.
4516 NearLabel compare_chars;
4517 __ bind(&check_zero_length);
4518 STATIC_ASSERT(kSmiTag == 0);
4519 __ SmiTest(length);
4520 __ j(not_zero, &compare_chars);
4521 __ Move(rax, Smi::FromInt(EQUAL));
4522 __ ret(0);
4523
4524 // Compare characters.
4525 __ bind(&compare_chars);
4526
4527 // Change index to run from -length to -1 by adding length to string
4528 // start. This means that loop ends when index reaches zero, which
4529 // doesn't need an additional compare.
4530 __ SmiToInteger32(length, length);
4531 __ lea(left,
4532 FieldOperand(left, length, times_1, SeqAsciiString::kHeaderSize));
4533 __ lea(right,
4534 FieldOperand(right, length, times_1, SeqAsciiString::kHeaderSize));
4535 __ neg(length);
4536 Register index = length; // index = -length;
4537
4538 // Compare loop.
4539 NearLabel strings_not_equal, loop;
4540 __ bind(&loop);
4541 __ movb(scratch2, Operand(left, index, times_1, 0));
Mads Ager (chromium) 2011/05/05 07:42:24 Do you need "times_1, 0" here?
Vitaly Repeshko 2011/05/05 11:40:18 Same here.
4542 __ cmpb(scratch2, Operand(right, index, times_1, 0));
4543 __ j(not_equal, &strings_not_equal);
4544 __ addq(index, Immediate(1));
4545 __ j(not_zero, &loop);
4546
4547 // Characters are equal.
4548 __ Move(rax, Smi::FromInt(EQUAL));
4549 __ ret(0);
4550
4551 // Characters are not equal.
4552 __ bind(&strings_not_equal);
4553 __ Move(rax, Smi::FromInt(NOT_EQUAL));
4554 __ ret(0);
4555 }
4556
4557
4492 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, 4558 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
4493 Register left, 4559 Register left,
4494 Register right, 4560 Register right,
4495 Register scratch1, 4561 Register scratch1,
4496 Register scratch2, 4562 Register scratch2,
4497 Register scratch3, 4563 Register scratch3,
4498 Register scratch4) { 4564 Register scratch4) {
4499 // Ensure that you can always subtract a string length from a non-negative 4565 // Ensure that you can always subtract a string length from a non-negative
4500 // number (e.g. another length). 4566 // number (e.g. another length).
4501 STATIC_ASSERT(String::kMaxLength < 0x7fffffff); 4567 STATIC_ASSERT(String::kMaxLength < 0x7fffffff);
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
4680 __ bind(&generic_stub); 4746 __ bind(&generic_stub);
4681 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); 4747 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET);
4682 4748
4683 __ bind(&miss); 4749 __ bind(&miss);
4684 GenerateMiss(masm); 4750 GenerateMiss(masm);
4685 } 4751 }
4686 4752
4687 4753
4688 void ICCompareStub::GenerateStrings(MacroAssembler* masm) { 4754 void ICCompareStub::GenerateStrings(MacroAssembler* masm) {
4689 ASSERT(state_ == CompareIC::STRINGS); 4755 ASSERT(state_ == CompareIC::STRINGS);
4756 ASSERT(GetCondition() == equal);
4690 Label miss; 4757 Label miss;
4691 4758
4692 // Registers containing left and right operands respectively. 4759 // Registers containing left and right operands respectively.
4693 Register left = rdx; 4760 Register left = rdx;
4694 Register right = rax; 4761 Register right = rax;
4695 Register tmp1 = rcx; 4762 Register tmp1 = rcx;
4696 Register tmp2 = rbx; 4763 Register tmp2 = rbx;
4697 Register tmp3 = rdi; 4764 Register tmp3 = rdi;
4698 Register tmp4 = r8;
4699 4765
4700 // Check that both operands are heap objects. 4766 // Check that both operands are heap objects.
4701 Condition cond = masm->CheckEitherSmi(left, right, tmp1); 4767 Condition cond = masm->CheckEitherSmi(left, right, tmp1);
4702 __ j(cond, &miss); 4768 __ j(cond, &miss);
4703 4769
4704 // Check that both operands are strings. This leaves the instance 4770 // Check that both operands are strings. This leaves the instance
4705 // types loaded in tmp1 and tmp2. 4771 // types loaded in tmp1 and tmp2.
4706 __ movq(tmp1, FieldOperand(left, HeapObject::kMapOffset)); 4772 __ movq(tmp1, FieldOperand(left, HeapObject::kMapOffset));
4707 __ movq(tmp2, FieldOperand(right, HeapObject::kMapOffset)); 4773 __ movq(tmp2, FieldOperand(right, HeapObject::kMapOffset));
4708 __ movzxbq(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); 4774 __ movzxbq(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
(...skipping 12 matching lines...) Expand all
4721 STATIC_ASSERT(kSmiTag == 0); 4787 STATIC_ASSERT(kSmiTag == 0);
4722 __ Move(rax, Smi::FromInt(EQUAL)); 4788 __ Move(rax, Smi::FromInt(EQUAL));
4723 __ ret(0); 4789 __ ret(0);
4724 4790
4725 // Handle not identical strings. 4791 // Handle not identical strings.
4726 __ bind(&not_same); 4792 __ bind(&not_same);
4727 4793
4728 // Check that both strings are symbols. If they are, we're done 4794 // Check that both strings are symbols. If they are, we're done
4729 // because we already know they are not identical. 4795 // because we already know they are not identical.
4730 NearLabel do_compare; 4796 NearLabel do_compare;
4731 ASSERT(GetCondition() == equal);
4732 STATIC_ASSERT(kSymbolTag != 0); 4797 STATIC_ASSERT(kSymbolTag != 0);
4733 __ and_(tmp1, tmp2); 4798 __ and_(tmp1, tmp2);
4734 __ testl(tmp1, Immediate(kIsSymbolMask)); 4799 __ testl(tmp1, Immediate(kIsSymbolMask));
4735 __ j(zero, &do_compare); 4800 __ j(zero, &do_compare);
4736 // Make sure rax is non-zero. At this point input operands are 4801 // Make sure rax is non-zero. At this point input operands are
4737 // guaranteed to be non-zero. 4802 // guaranteed to be non-zero.
4738 ASSERT(right.is(rax)); 4803 ASSERT(right.is(rax));
4739 __ ret(0); 4804 __ ret(0);
4740 4805
4741 // Check that both strings are sequential ASCII. 4806 // Check that both strings are sequential ASCII.
4742 Label runtime; 4807 Label runtime;
4743 __ bind(&do_compare); 4808 __ bind(&do_compare);
4744 __ JumpIfNotBothSequentialAsciiStrings(left, right, tmp1, tmp2, &runtime); 4809 __ JumpIfNotBothSequentialAsciiStrings(left, right, tmp1, tmp2, &runtime);
4745 4810
4746 // Compare flat ASCII strings. Returns when done. 4811 // Compare flat ASCII strings. Returns when done.
4747 StringCompareStub::GenerateCompareFlatAsciiStrings( 4812 StringCompareStub::GenerateFlatAsciiStringEquals(
4748 masm, left, right, tmp1, tmp2, tmp3, tmp4); 4813 masm, left, right, tmp1, tmp2);
4749 4814
4750 // Handle more complex cases in runtime. 4815 // Handle more complex cases in runtime.
4751 __ bind(&runtime); 4816 __ bind(&runtime);
4752 __ pop(tmp1); // Return address. 4817 __ pop(tmp1); // Return address.
4753 __ push(left); 4818 __ push(left);
4754 __ push(right); 4819 __ push(right);
4755 __ push(tmp1); 4820 __ push(tmp1);
4756 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 4821 __ TailCallRuntime(Runtime::kStringEquals, 2, 1);
4757 4822
4758 __ bind(&miss); 4823 __ bind(&miss);
4759 GenerateMiss(masm); 4824 GenerateMiss(masm);
4760 } 4825 }
4761 4826
4762 4827
4763 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { 4828 void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
4764 ASSERT(state_ == CompareIC::OBJECTS); 4829 ASSERT(state_ == CompareIC::OBJECTS);
4765 NearLabel miss; 4830 NearLabel miss;
4766 Condition either_smi = masm->CheckEitherSmi(rdx, rax); 4831 Condition either_smi = masm->CheckEitherSmi(rdx, rax);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
4809 // Do a tail call to the rewritten stub. 4874 // Do a tail call to the rewritten stub.
4810 __ jmp(rdi); 4875 __ jmp(rdi);
4811 } 4876 }
4812 4877
4813 4878
4814 #undef __ 4879 #undef __
4815 4880
4816 } } // namespace v8::internal 4881 } } // namespace v8::internal
4817 4882
4818 #endif // V8_TARGET_ARCH_X64 4883 #endif // V8_TARGET_ARCH_X64
OLDNEW
« src/ia32/code-stubs-ia32.cc ('K') | « src/x64/code-stubs-x64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698