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

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

Issue 6932010: Unroll more StringDictionary lookup probes both for positive and negative dictionary lookups. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: ported to arm&x64, cleaned up ia32 impl 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 | Annotate | Revision Log
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 978 matching lines...) Expand 10 before | Expand all | Expand 10 after
989 __ movq(FieldOperand(rax, HeapObject::kMapOffset), 989 __ movq(FieldOperand(rax, HeapObject::kMapOffset),
990 heap_number_map); 990 heap_number_map);
991 __ cvtqsi2sd(xmm0, rbx); 991 __ cvtqsi2sd(xmm0, rbx);
992 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0); 992 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0);
993 __ Ret(); 993 __ Ret();
994 994
995 __ bind(&allocation_failed); 995 __ bind(&allocation_failed);
996 // We need tagged values in rdx and rax for the following code, 996 // We need tagged values in rdx and rax for the following code,
997 // not int32 in rax and rcx. 997 // not int32 in rax and rcx.
998 __ Integer32ToSmi(rax, rcx); 998 __ Integer32ToSmi(rax, rcx);
999 __ Integer32ToSmi(rdx, rax); 999 __ Integer32ToSmi(rdx, rbx);
Mads Ager (chromium) 2011/05/05 11:54:56 This is fixed in Florian's commit too, right?
Vyacheslav Egorov (Chromium) 2011/05/05 12:30:16 Yep, this is accidental change.
1000 __ jmp(allocation_failure); 1000 __ jmp(allocation_failure);
1001 } 1001 }
1002 break; 1002 break;
1003 } 1003 }
1004 default: UNREACHABLE(); break; 1004 default: UNREACHABLE(); break;
1005 } 1005 }
1006 // No fall-through from this generated code. 1006 // No fall-through from this generated code.
1007 if (FLAG_debug_code) { 1007 if (FLAG_debug_code) {
1008 __ Abort("Unexpected fall-through in " 1008 __ Abort("Unexpected fall-through in "
1009 "TypeRecordingBinaryStub::GenerateFloatingPointCode."); 1009 "TypeRecordingBinaryStub::GenerateFloatingPointCode.");
(...skipping 3719 matching lines...) Expand 10 before | Expand all | Expand 10 after
4729 __ pop(rcx); 4729 __ pop(rcx);
4730 __ pop(rax); 4730 __ pop(rax);
4731 __ pop(rdx); 4731 __ pop(rdx);
4732 __ push(rcx); 4732 __ push(rcx);
4733 4733
4734 // Do a tail call to the rewritten stub. 4734 // Do a tail call to the rewritten stub.
4735 __ jmp(rdi); 4735 __ jmp(rdi);
4736 } 4736 }
4737 4737
4738 4738
4739 void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
4740 Label* miss,
4741 Label* done,
4742 Register properties,
4743 String* name,
4744 Register r0) {
4745 // If names of slots in range from 1 to kProbes - 1 for the hash value are
4746 // not equal to the name and kProbes-th slot is not used (its name is the
4747 // undefined value), it guarantees the hash table doesn't contain the
4748 // property. It's true even if some slots represent deleted properties
4749 // (their names are the null value).
4750 for (int i = 0; i < kInlinedProbes; i++) {
4751 // r0 points to properties hash.
4752 // Compute the masked index: (hash + i + i * i) & mask.
4753 Register index = r0;
4754 // Capacity is smi 2^n.
4755 __ SmiToInteger32(index, FieldOperand(properties, kCapacityOffset));
4756 __ decl(index);
4757 __ and_(index,
Lasse Reichstein 2011/05/05 14:20:13 Use andl instead of and_, one byte shorter.
4758 Immediate(name->Hash() + StringDictionary::GetProbeOffset(i)));
4759
4760 // Scale the index by multiplying by the entry size.
4761 ASSERT(StringDictionary::kEntrySize == 3);
4762 __ lea(index, Operand(index, index, times_2, 0)); // index *= 3.
Lasse Reichstein 2011/05/05 14:20:13 Use leal instead of lea for 32-bit operations - un
4763
4764 Register entity_name = r0;
4765 // Having undefined at this place means the name is not contained.
4766 ASSERT_EQ(kSmiTagSize, 1);
4767 __ movq(entity_name, Operand(properties,
4768 index,
4769 times_pointer_size,
4770 kElementsStartOffset - kHeapObjectTag));
4771 __ Cmp(entity_name, masm->isolate()->factory()->undefined_value());
Lasse Reichstein 2011/05/05 14:20:13 We typically use CompareRoot for this.
4772 __ j(equal, done);
4773
4774 // Stop if found the property.
4775 __ Cmp(entity_name, Handle<String>(name));
4776 __ j(equal, miss);
4777
4778 // Check if the entry name is not a symbol.
4779 __ movq(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
4780 __ testb(FieldOperand(entity_name, Map::kInstanceTypeOffset),
4781 Immediate(kIsSymbolMask));
4782 __ j(zero, miss);
4783 }
4784
4785 StringDictionaryLookupStub stub(properties,
4786 r0,
4787 r0,
4788 StringDictionaryLookupStub::NEGATIVE_LOOKUP);
4789 __ Push(Handle<Object>(name));
4790 __ push(Immediate(name->Hash()));
4791 __ CallStub(&stub);
4792 __ testq(r0, r0);
Lasse Reichstein 2011/05/05 14:20:13 If the result is guaranteed to have its nonzero bi
4793 __ j(not_zero, miss);
4794 __ jmp(done);
4795 }
4796
4797
4798 // Probe the string dictionary in the |elements| register. Jump to the
4799 // |done| label if a property with the given name is found leaving the
4800 // index into the dictionary in |r1|. Jump to the |miss| label
4801 // otherwise.
4802 void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
4803 Label* miss,
4804 Label* done,
4805 Register elements,
4806 Register name,
4807 Register r0,
4808 Register r1) {
4809 // Assert that name contains a string.
4810 if (FLAG_debug_code) __ AbortIfNotString(name);
4811
4812 __ SmiToInteger32(r0, FieldOperand(elements, kCapacityOffset));
4813 __ decl(r0);
4814
4815 for (int i = 0; i < kInlinedProbes; i++) {
4816 // Compute the masked index: (hash + i + i * i) & mask.
4817 __ movl(r1, FieldOperand(name, String::kHashFieldOffset));
4818 __ shrl(r1, Immediate(String::kHashShift));
4819 if (i > 0) {
4820 __ addl(r1, Immediate(StringDictionary::GetProbeOffset(i)));
4821 }
4822 __ and_(r1, r0);
Lasse Reichstein 2011/05/05 14:20:13 andl
4823
4824 // Scale the index by multiplying by the entry size.
4825 ASSERT(StringDictionary::kEntrySize == 3);
4826 __ lea(r1, Operand(r1, r1, times_2, 0)); // r1 = r1 * 3
Lasse Reichstein 2011/05/05 14:20:13 leal
4827
4828 // Check if the key is identical to the name.
4829 __ cmpq(name, Operand(elements, r1, times_pointer_size,
4830 kElementsStartOffset - kHeapObjectTag));
4831 __ j(equal, done);
4832 }
4833
4834 StringDictionaryLookupStub stub(elements,
4835 r0,
4836 r1,
4837 POSITIVE_LOOKUP);
4838 __ push(name);
4839 __ movl(r0, FieldOperand(name, String::kHashFieldOffset));
4840 __ shrl(r0, Immediate(String::kHashShift));
4841 __ push(r0);
4842 __ CallStub(&stub);
4843
4844 __ testq(r0, r0);
Lasse Reichstein 2011/05/05 14:20:13 Possibly testl.
4845 __ j(zero, miss);
4846 __ jmp(done);
4847 }
4848
4849
4850 void StringDictionaryLookupStub::Generate(MacroAssembler* masm) {
4851 // Stack frame on entry:
4852 // esp[0 * kPointerSize]: return address.
Lasse Reichstein 2011/05/05 14:20:13 esp->rsp
4853 // esp[1 * kPointerSize]: key's hash.
4854 // esp[2 * kPointerSize]: key.
4855 // Registers:
4856 // dictionary_: StringDictionary to probe.
4857 // result_: used as scratch.
4858 // index_: will hold an index of entry if lookup is successful.
4859 // might alias with result_.
4860 // Returns:
4861 // result_ is zero if lookup failed, non zero otherwise.
Lasse Reichstein 2011/05/05 14:20:13 Document that it's nonzero when used as a double-w
4862
4863 Label in_dictionary, maybe_in_dictionary, not_in_dictionary;
4864
4865 Register scratch = result_;
4866
4867 __ SmiToInteger32(scratch, FieldOperand(dictionary_, kCapacityOffset));
4868 __ decl(scratch);
4869 __ push(scratch);
4870
4871 // If names of slots in range from 1 to kProbes - 1 for the hash value are
4872 // not equal to the name and kProbes-th slot is not used (its name is the
4873 // undefined value), it guarantees the hash table doesn't contain the
4874 // property. It's true even if some slots represent deleted properties
4875 // (their names are the null value).
4876 for (int i = kInlinedProbes; i < kTotalProbes; i++) {
4877 // Compute the masked index: (hash + i + i * i) & mask.
4878 __ movq(scratch, Operand(rsp, 2 * kPointerSize));
4879 if (i > 0) {
4880 __ addl(scratch, Immediate(StringDictionary::GetProbeOffset(i)));
4881 }
4882 __ and_(scratch, Operand(rsp, 0));
Lasse Reichstein 2011/05/05 14:20:13 andl
4883
4884 // Scale the index by multiplying by the entry size.
4885 ASSERT(StringDictionary::kEntrySize == 3);
4886 __ lea(index_, Operand(scratch, scratch, times_2, 0)); // index *= 3.
Lasse Reichstein 2011/05/05 14:20:13 leal
4887
4888 // Having undefined at this place means the name is not contained.
4889 __ movq(scratch, Operand(dictionary_,
4890 index_,
4891 times_pointer_size,
4892 kElementsStartOffset - kHeapObjectTag));
4893
4894 __ Cmp(scratch, masm->isolate()->factory()->undefined_value());
Lasse Reichstein 2011/05/05 14:20:13 CompareRoot
4895 __ j(equal, &not_in_dictionary);
4896
4897 // Stop if found the property.
4898 __ cmpq(scratch, Operand(rsp, 3 * kPointerSize));
4899 __ j(equal, &in_dictionary);
4900
4901 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
4902 // If we hit a non symbol key during negative lookup
4903 // we have to bailout as this key might be equal to the
4904 // key we are looking for.
4905
4906 // Check if the entry name is not a symbol.
4907 __ movq(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
4908 __ testb(FieldOperand(scratch, Map::kInstanceTypeOffset),
4909 Immediate(kIsSymbolMask));
4910 __ j(zero, &maybe_in_dictionary);
4911 }
4912 }
4913
4914 __ bind(&maybe_in_dictionary);
4915 // If we are doing negative lookup then probing failure should be
4916 // treated as a lookup success. For positive lookup probing failure
4917 // should be treated as lookup failure.
4918 if (mode_ == POSITIVE_LOOKUP) {
4919 __ movq(scratch, Immediate(0));
Lasse Reichstein 2011/05/05 14:20:13 __ Move(scratch, 0); // will use xor
4920 __ Drop(1);
4921 __ ret(2 * kPointerSize);
4922 }
4923
4924 __ bind(&in_dictionary);
4925 __ movq(scratch, Immediate(1));
Lasse Reichstein 2011/05/05 14:20:13 Consider using Move
4926 __ Drop(1);
4927 __ ret(2 * kPointerSize);
4928
4929 __ bind(&not_in_dictionary);
4930 __ movq(scratch, Immediate(0));
Lasse Reichstein 2011/05/05 14:20:13 Use Move.
4931 __ Drop(1);
4932 __ ret(2 * kPointerSize);
4933 }
4934
4935
4739 #undef __ 4936 #undef __
4740 4937
4741 } } // namespace v8::internal 4938 } } // namespace v8::internal
4742 4939
4743 #endif // V8_TARGET_ARCH_X64 4940 #endif // V8_TARGET_ARCH_X64
OLDNEW
« src/x64/code-stubs-x64.h ('K') | « src/x64/code-stubs-x64.h ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698