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 5841 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5852 __ pop(ecx); | 5852 __ pop(ecx); |
5853 __ pop(eax); | 5853 __ pop(eax); |
5854 __ pop(edx); | 5854 __ pop(edx); |
5855 __ push(ecx); | 5855 __ push(ecx); |
5856 | 5856 |
5857 // Do a tail call to the rewritten stub. | 5857 // Do a tail call to the rewritten stub. |
5858 __ jmp(Operand(edi)); | 5858 __ jmp(Operand(edi)); |
5859 } | 5859 } |
5860 | 5860 |
5861 | 5861 |
| 5862 void StringDictionaryLookupStub::Generate(MacroAssembler* masm) { |
| 5863 // Stack frame on entry: |
| 5864 // esp[0]: return address. |
| 5865 // esp[4]: key's hash. |
| 5866 // esp[8]: key. |
| 5867 // Registers: |
| 5868 // dictionary_: StringDictionary to probe. |
| 5869 // result_: used as scratch. |
| 5870 // index_: will hold an index of entry if lookup is successful. |
| 5871 // might alias with result_. |
| 5872 // Returns: |
| 5873 // result_ is zero if lookup failed, non zero otherwise. |
| 5874 |
| 5875 Label in_dictionary, maybe_in_dictionary, not_in_dictionary; |
| 5876 |
| 5877 // Compute the capacity mask. |
| 5878 const int kCapacityOffset = |
| 5879 StringDictionary::kHeaderSize + |
| 5880 StringDictionary::kCapacityIndex * kPointerSize; |
| 5881 |
| 5882 // Generate an unrolled loop that performs a few probes before |
| 5883 // giving up. |
| 5884 static const int kFirstProbe = 4; |
| 5885 static const int kProbes = 20; |
| 5886 const int kElementsStartOffset = |
| 5887 StringDictionary::kHeaderSize + |
| 5888 StringDictionary::kElementsStartIndex * kPointerSize; |
| 5889 |
| 5890 Register scratch = result_; |
| 5891 |
| 5892 __ mov(scratch, FieldOperand(dictionary_, kCapacityOffset)); |
| 5893 __ dec(scratch); |
| 5894 __ SmiUntag(scratch); |
| 5895 __ push(scratch); |
| 5896 |
| 5897 // If names of slots in range from 1 to kProbes - 1 for the hash value are |
| 5898 // not equal to the name and kProbes-th slot is not used (its name is the |
| 5899 // undefined value), it guarantees the hash table doesn't contain the |
| 5900 // property. It's true even if some slots represent deleted properties |
| 5901 // (their names are the null value). |
| 5902 for (int i = kFirstProbe; i < kProbes; i++) { |
| 5903 // Compute the masked index: (hash + i + i * i) & mask. |
| 5904 __ mov(scratch, Operand(esp, 2 * kPointerSize)); |
| 5905 if (i > 0) { |
| 5906 __ add(Operand(scratch), |
| 5907 Immediate(StringDictionary::GetProbeOffset(i))); |
| 5908 } |
| 5909 __ and_(scratch, Operand(esp, 0)); |
| 5910 |
| 5911 // Scale the index by multiplying by the entry size. |
| 5912 ASSERT(StringDictionary::kEntrySize == 3); |
| 5913 __ lea(index_, Operand(scratch, scratch, times_2, 0)); // index *= 3. |
| 5914 |
| 5915 // Having undefined at this place means the name is not contained. |
| 5916 ASSERT_EQ(kSmiTagSize, 1); |
| 5917 __ mov(scratch, Operand(dictionary_, |
| 5918 index_, |
| 5919 times_pointer_size, |
| 5920 kElementsStartOffset - kHeapObjectTag)); |
| 5921 __ cmp(scratch, masm->isolate()->factory()->undefined_value()); |
| 5922 __ j(equal, ¬_in_dictionary); |
| 5923 |
| 5924 if (i != kProbes - 1) { |
| 5925 // Stop if found the property. |
| 5926 __ cmp(scratch, Operand(esp, 3 * kPointerSize)); |
| 5927 __ j(equal, &in_dictionary); |
| 5928 |
| 5929 if (mode_ == NEGATIVE_LOOKUP) { |
| 5930 // If we hit a non symbol key during negative lookup |
| 5931 // we have to bailout as this key might be equal to the |
| 5932 // key we are looking for. |
| 5933 |
| 5934 // Check if the entry name is not a symbol. |
| 5935 __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); |
| 5936 __ test_b(FieldOperand(scratch, Map::kInstanceTypeOffset), |
| 5937 kIsSymbolMask); |
| 5938 __ j(zero, &maybe_in_dictionary); |
| 5939 } |
| 5940 } |
| 5941 } |
| 5942 |
| 5943 __ bind(&maybe_in_dictionary); |
| 5944 // If we are doing negative lookup then probing failure should be |
| 5945 // treated as a lookup success. For positive lookup probing failure |
| 5946 // should be treated as lookup failure. |
| 5947 if (mode_ == POSITIVE_LOOKUP) { |
| 5948 __ mov(scratch, Immediate(0)); |
| 5949 __ Drop(1); |
| 5950 __ ret(2 * kPointerSize); |
| 5951 } |
| 5952 |
| 5953 __ bind(&in_dictionary); |
| 5954 __ mov(scratch, Immediate(1)); |
| 5955 __ Drop(1); |
| 5956 __ ret(2 * kPointerSize); |
| 5957 |
| 5958 __ bind(¬_in_dictionary); |
| 5959 __ mov(scratch, Immediate(0)); |
| 5960 __ Drop(1); |
| 5961 __ ret(2 * kPointerSize); |
| 5962 } |
| 5963 |
| 5964 |
5862 #undef __ | 5965 #undef __ |
5863 | 5966 |
5864 } } // namespace v8::internal | 5967 } } // namespace v8::internal |
5865 | 5968 |
5866 #endif // V8_TARGET_ARCH_IA32 | 5969 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |