OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 6084 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6095 __ lea(rdi, FieldOperand(rax, Code::kHeaderSize)); | 6095 __ lea(rdi, FieldOperand(rax, Code::kHeaderSize)); |
6096 __ pop(rax); | 6096 __ pop(rax); |
6097 __ pop(rdx); | 6097 __ pop(rdx); |
6098 } | 6098 } |
6099 | 6099 |
6100 // Do a tail call to the rewritten stub. | 6100 // Do a tail call to the rewritten stub. |
6101 __ jmp(rdi); | 6101 __ jmp(rdi); |
6102 } | 6102 } |
6103 | 6103 |
6104 | 6104 |
6105 void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, | 6105 void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, |
6106 Label* miss, | 6106 Label* miss, |
6107 Label* done, | 6107 Label* done, |
6108 Register properties, | 6108 Register properties, |
6109 Handle<String> name, | 6109 Handle<Name> name, |
6110 Register r0) { | 6110 Register r0) { |
| 6111 ASSERT(name->IsUniqueName()); |
6111 // If names of slots in range from 1 to kProbes - 1 for the hash value are | 6112 // If names of slots in range from 1 to kProbes - 1 for the hash value are |
6112 // not equal to the name and kProbes-th slot is not used (its name is the | 6113 // not equal to the name and kProbes-th slot is not used (its name is the |
6113 // undefined value), it guarantees the hash table doesn't contain the | 6114 // undefined value), it guarantees the hash table doesn't contain the |
6114 // property. It's true even if some slots represent deleted properties | 6115 // property. It's true even if some slots represent deleted properties |
6115 // (their names are the hole value). | 6116 // (their names are the hole value). |
6116 for (int i = 0; i < kInlinedProbes; i++) { | 6117 for (int i = 0; i < kInlinedProbes; i++) { |
6117 // r0 points to properties hash. | 6118 // r0 points to properties hash. |
6118 // Compute the masked index: (hash + i + i * i) & mask. | 6119 // Compute the masked index: (hash + i + i * i) & mask. |
6119 Register index = r0; | 6120 Register index = r0; |
6120 // Capacity is smi 2^n. | 6121 // Capacity is smi 2^n. |
6121 __ SmiToInteger32(index, FieldOperand(properties, kCapacityOffset)); | 6122 __ SmiToInteger32(index, FieldOperand(properties, kCapacityOffset)); |
6122 __ decl(index); | 6123 __ decl(index); |
6123 __ and_(index, | 6124 __ and_(index, |
6124 Immediate(name->Hash() + StringDictionary::GetProbeOffset(i))); | 6125 Immediate(name->Hash() + NameDictionary::GetProbeOffset(i))); |
6125 | 6126 |
6126 // Scale the index by multiplying by the entry size. | 6127 // Scale the index by multiplying by the entry size. |
6127 ASSERT(StringDictionary::kEntrySize == 3); | 6128 ASSERT(NameDictionary::kEntrySize == 3); |
6128 __ lea(index, Operand(index, index, times_2, 0)); // index *= 3. | 6129 __ lea(index, Operand(index, index, times_2, 0)); // index *= 3. |
6129 | 6130 |
6130 Register entity_name = r0; | 6131 Register entity_name = r0; |
6131 // Having undefined at this place means the name is not contained. | 6132 // Having undefined at this place means the name is not contained. |
6132 ASSERT_EQ(kSmiTagSize, 1); | 6133 ASSERT_EQ(kSmiTagSize, 1); |
6133 __ movq(entity_name, Operand(properties, | 6134 __ movq(entity_name, Operand(properties, |
6134 index, | 6135 index, |
6135 times_pointer_size, | 6136 times_pointer_size, |
6136 kElementsStartOffset - kHeapObjectTag)); | 6137 kElementsStartOffset - kHeapObjectTag)); |
6137 __ Cmp(entity_name, masm->isolate()->factory()->undefined_value()); | 6138 __ Cmp(entity_name, masm->isolate()->factory()->undefined_value()); |
6138 __ j(equal, done); | 6139 __ j(equal, done); |
6139 | 6140 |
6140 // Stop if found the property. | 6141 // Stop if found the property. |
6141 __ Cmp(entity_name, Handle<String>(name)); | 6142 __ Cmp(entity_name, Handle<Name>(name)); |
6142 __ j(equal, miss); | 6143 __ j(equal, miss); |
6143 | 6144 |
6144 Label the_hole; | 6145 Label good; |
6145 // Check for the hole and skip. | 6146 // Check for the hole and skip. |
6146 __ CompareRoot(entity_name, Heap::kTheHoleValueRootIndex); | 6147 __ CompareRoot(entity_name, Heap::kTheHoleValueRootIndex); |
6147 __ j(equal, &the_hole, Label::kNear); | 6148 __ j(equal, &good, Label::kNear); |
6148 | 6149 |
6149 // Check if the entry name is not an internalized string. | 6150 // Check if the entry name is not a unique name. |
6150 __ movq(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset)); | 6151 __ movq(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset)); |
6151 __ testb(FieldOperand(entity_name, Map::kInstanceTypeOffset), | 6152 __ testb(FieldOperand(entity_name, Map::kInstanceTypeOffset), |
6152 Immediate(kIsInternalizedMask)); | 6153 Immediate(kIsInternalizedMask)); |
6153 __ j(zero, miss); | 6154 __ j(not_zero, &good, Label::kNear); |
| 6155 __ cmpb(FieldOperand(entity_name, Map::kInstanceTypeOffset), |
| 6156 Immediate(static_cast<int8_t>(SYMBOL_TYPE))); |
| 6157 __ j(not_equal, miss); |
6154 | 6158 |
6155 __ bind(&the_hole); | 6159 __ bind(&good); |
6156 } | 6160 } |
6157 | 6161 |
6158 StringDictionaryLookupStub stub(properties, | 6162 NameDictionaryLookupStub stub(properties, r0, r0, NEGATIVE_LOOKUP); |
6159 r0, | |
6160 r0, | |
6161 StringDictionaryLookupStub::NEGATIVE_LOOKUP); | |
6162 __ Push(Handle<Object>(name)); | 6163 __ Push(Handle<Object>(name)); |
6163 __ push(Immediate(name->Hash())); | 6164 __ push(Immediate(name->Hash())); |
6164 __ CallStub(&stub); | 6165 __ CallStub(&stub); |
6165 __ testq(r0, r0); | 6166 __ testq(r0, r0); |
6166 __ j(not_zero, miss); | 6167 __ j(not_zero, miss); |
6167 __ jmp(done); | 6168 __ jmp(done); |
6168 } | 6169 } |
6169 | 6170 |
6170 | 6171 |
6171 // Probe the string dictionary in the |elements| register. Jump to the | 6172 // Probe the name dictionary in the |elements| register. Jump to the |
6172 // |done| label if a property with the given name is found leaving the | 6173 // |done| label if a property with the given name is found leaving the |
6173 // index into the dictionary in |r1|. Jump to the |miss| label | 6174 // index into the dictionary in |r1|. Jump to the |miss| label |
6174 // otherwise. | 6175 // otherwise. |
6175 void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, | 6176 void NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, |
6176 Label* miss, | 6177 Label* miss, |
6177 Label* done, | 6178 Label* done, |
6178 Register elements, | 6179 Register elements, |
6179 Register name, | 6180 Register name, |
6180 Register r0, | 6181 Register r0, |
6181 Register r1) { | 6182 Register r1) { |
6182 ASSERT(!elements.is(r0)); | 6183 ASSERT(!elements.is(r0)); |
6183 ASSERT(!elements.is(r1)); | 6184 ASSERT(!elements.is(r1)); |
6184 ASSERT(!name.is(r0)); | 6185 ASSERT(!name.is(r0)); |
6185 ASSERT(!name.is(r1)); | 6186 ASSERT(!name.is(r1)); |
6186 | 6187 |
6187 __ AssertString(name); | 6188 __ AssertName(name); |
6188 | 6189 |
6189 __ SmiToInteger32(r0, FieldOperand(elements, kCapacityOffset)); | 6190 __ SmiToInteger32(r0, FieldOperand(elements, kCapacityOffset)); |
6190 __ decl(r0); | 6191 __ decl(r0); |
6191 | 6192 |
6192 for (int i = 0; i < kInlinedProbes; i++) { | 6193 for (int i = 0; i < kInlinedProbes; i++) { |
6193 // Compute the masked index: (hash + i + i * i) & mask. | 6194 // Compute the masked index: (hash + i + i * i) & mask. |
6194 __ movl(r1, FieldOperand(name, String::kHashFieldOffset)); | 6195 __ movl(r1, FieldOperand(name, Name::kHashFieldOffset)); |
6195 __ shrl(r1, Immediate(String::kHashShift)); | 6196 __ shrl(r1, Immediate(Name::kHashShift)); |
6196 if (i > 0) { | 6197 if (i > 0) { |
6197 __ addl(r1, Immediate(StringDictionary::GetProbeOffset(i))); | 6198 __ addl(r1, Immediate(NameDictionary::GetProbeOffset(i))); |
6198 } | 6199 } |
6199 __ and_(r1, r0); | 6200 __ and_(r1, r0); |
6200 | 6201 |
6201 // Scale the index by multiplying by the entry size. | 6202 // Scale the index by multiplying by the entry size. |
6202 ASSERT(StringDictionary::kEntrySize == 3); | 6203 ASSERT(NameDictionary::kEntrySize == 3); |
6203 __ lea(r1, Operand(r1, r1, times_2, 0)); // r1 = r1 * 3 | 6204 __ lea(r1, Operand(r1, r1, times_2, 0)); // r1 = r1 * 3 |
6204 | 6205 |
6205 // Check if the key is identical to the name. | 6206 // Check if the key is identical to the name. |
6206 __ cmpq(name, Operand(elements, r1, times_pointer_size, | 6207 __ cmpq(name, Operand(elements, r1, times_pointer_size, |
6207 kElementsStartOffset - kHeapObjectTag)); | 6208 kElementsStartOffset - kHeapObjectTag)); |
6208 __ j(equal, done); | 6209 __ j(equal, done); |
6209 } | 6210 } |
6210 | 6211 |
6211 StringDictionaryLookupStub stub(elements, | 6212 NameDictionaryLookupStub stub(elements, r0, r1, POSITIVE_LOOKUP); |
6212 r0, | |
6213 r1, | |
6214 POSITIVE_LOOKUP); | |
6215 __ push(name); | 6213 __ push(name); |
6216 __ movl(r0, FieldOperand(name, String::kHashFieldOffset)); | 6214 __ movl(r0, FieldOperand(name, Name::kHashFieldOffset)); |
6217 __ shrl(r0, Immediate(String::kHashShift)); | 6215 __ shrl(r0, Immediate(Name::kHashShift)); |
6218 __ push(r0); | 6216 __ push(r0); |
6219 __ CallStub(&stub); | 6217 __ CallStub(&stub); |
6220 | 6218 |
6221 __ testq(r0, r0); | 6219 __ testq(r0, r0); |
6222 __ j(zero, miss); | 6220 __ j(zero, miss); |
6223 __ jmp(done); | 6221 __ jmp(done); |
6224 } | 6222 } |
6225 | 6223 |
6226 | 6224 |
6227 void StringDictionaryLookupStub::Generate(MacroAssembler* masm) { | 6225 void NameDictionaryLookupStub::Generate(MacroAssembler* masm) { |
6228 // This stub overrides SometimesSetsUpAFrame() to return false. That means | 6226 // This stub overrides SometimesSetsUpAFrame() to return false. That means |
6229 // we cannot call anything that could cause a GC from this stub. | 6227 // we cannot call anything that could cause a GC from this stub. |
6230 // Stack frame on entry: | 6228 // Stack frame on entry: |
6231 // esp[0 * kPointerSize]: return address. | 6229 // esp[0 * kPointerSize]: return address. |
6232 // esp[1 * kPointerSize]: key's hash. | 6230 // esp[1 * kPointerSize]: key's hash. |
6233 // esp[2 * kPointerSize]: key. | 6231 // esp[2 * kPointerSize]: key. |
6234 // Registers: | 6232 // Registers: |
6235 // dictionary_: StringDictionary to probe. | 6233 // dictionary_: NameDictionary to probe. |
6236 // result_: used as scratch. | 6234 // result_: used as scratch. |
6237 // index_: will hold an index of entry if lookup is successful. | 6235 // index_: will hold an index of entry if lookup is successful. |
6238 // might alias with result_. | 6236 // might alias with result_. |
6239 // Returns: | 6237 // Returns: |
6240 // result_ is zero if lookup failed, non zero otherwise. | 6238 // result_ is zero if lookup failed, non zero otherwise. |
6241 | 6239 |
6242 Label in_dictionary, maybe_in_dictionary, not_in_dictionary; | 6240 Label in_dictionary, maybe_in_dictionary, not_in_dictionary; |
6243 | 6241 |
6244 Register scratch = result_; | 6242 Register scratch = result_; |
6245 | 6243 |
6246 __ SmiToInteger32(scratch, FieldOperand(dictionary_, kCapacityOffset)); | 6244 __ SmiToInteger32(scratch, FieldOperand(dictionary_, kCapacityOffset)); |
6247 __ decl(scratch); | 6245 __ decl(scratch); |
6248 __ push(scratch); | 6246 __ push(scratch); |
6249 | 6247 |
6250 // If names of slots in range from 1 to kProbes - 1 for the hash value are | 6248 // If names of slots in range from 1 to kProbes - 1 for the hash value are |
6251 // not equal to the name and kProbes-th slot is not used (its name is the | 6249 // not equal to the name and kProbes-th slot is not used (its name is the |
6252 // undefined value), it guarantees the hash table doesn't contain the | 6250 // undefined value), it guarantees the hash table doesn't contain the |
6253 // property. It's true even if some slots represent deleted properties | 6251 // property. It's true even if some slots represent deleted properties |
6254 // (their names are the null value). | 6252 // (their names are the null value). |
6255 for (int i = kInlinedProbes; i < kTotalProbes; i++) { | 6253 for (int i = kInlinedProbes; i < kTotalProbes; i++) { |
6256 // Compute the masked index: (hash + i + i * i) & mask. | 6254 // Compute the masked index: (hash + i + i * i) & mask. |
6257 __ movq(scratch, Operand(rsp, 2 * kPointerSize)); | 6255 __ movq(scratch, Operand(rsp, 2 * kPointerSize)); |
6258 if (i > 0) { | 6256 if (i > 0) { |
6259 __ addl(scratch, Immediate(StringDictionary::GetProbeOffset(i))); | 6257 __ addl(scratch, Immediate(NameDictionary::GetProbeOffset(i))); |
6260 } | 6258 } |
6261 __ and_(scratch, Operand(rsp, 0)); | 6259 __ and_(scratch, Operand(rsp, 0)); |
6262 | 6260 |
6263 // Scale the index by multiplying by the entry size. | 6261 // Scale the index by multiplying by the entry size. |
6264 ASSERT(StringDictionary::kEntrySize == 3); | 6262 ASSERT(NameDictionary::kEntrySize == 3); |
6265 __ lea(index_, Operand(scratch, scratch, times_2, 0)); // index *= 3. | 6263 __ lea(index_, Operand(scratch, scratch, times_2, 0)); // index *= 3. |
6266 | 6264 |
6267 // Having undefined at this place means the name is not contained. | 6265 // Having undefined at this place means the name is not contained. |
6268 __ movq(scratch, Operand(dictionary_, | 6266 __ movq(scratch, Operand(dictionary_, |
6269 index_, | 6267 index_, |
6270 times_pointer_size, | 6268 times_pointer_size, |
6271 kElementsStartOffset - kHeapObjectTag)); | 6269 kElementsStartOffset - kHeapObjectTag)); |
6272 | 6270 |
6273 __ Cmp(scratch, masm->isolate()->factory()->undefined_value()); | 6271 __ Cmp(scratch, masm->isolate()->factory()->undefined_value()); |
6274 __ j(equal, ¬_in_dictionary); | 6272 __ j(equal, ¬_in_dictionary); |
6275 | 6273 |
6276 // Stop if found the property. | 6274 // Stop if found the property. |
6277 __ cmpq(scratch, Operand(rsp, 3 * kPointerSize)); | 6275 __ cmpq(scratch, Operand(rsp, 3 * kPointerSize)); |
6278 __ j(equal, &in_dictionary); | 6276 __ j(equal, &in_dictionary); |
6279 | 6277 |
6280 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { | 6278 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { |
6281 // If we hit a non internalized string key during negative lookup | 6279 // If we hit a key that is not a unique name during negative |
6282 // we have to bailout as this key might be equal to the | 6280 // lookup we have to bailout as this key might be equal to the |
6283 // key we are looking for. | 6281 // key we are looking for. |
6284 | 6282 |
6285 // Check if the entry name is not an internalized string. | 6283 // Check if the entry name is not a unique name. |
| 6284 Label cont; |
6286 __ movq(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); | 6285 __ movq(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); |
6287 __ testb(FieldOperand(scratch, Map::kInstanceTypeOffset), | 6286 __ testb(FieldOperand(scratch, Map::kInstanceTypeOffset), |
6288 Immediate(kIsInternalizedMask)); | 6287 Immediate(kIsInternalizedMask)); |
6289 __ j(zero, &maybe_in_dictionary); | 6288 __ j(not_zero, &cont); |
| 6289 __ cmpb(FieldOperand(scratch, Map::kInstanceTypeOffset), |
| 6290 Immediate(static_cast<int8_t>(SYMBOL_TYPE))); |
| 6291 __ j(not_equal, &maybe_in_dictionary); |
| 6292 __ bind(&cont); |
6290 } | 6293 } |
6291 } | 6294 } |
6292 | 6295 |
6293 __ bind(&maybe_in_dictionary); | 6296 __ bind(&maybe_in_dictionary); |
6294 // If we are doing negative lookup then probing failure should be | 6297 // If we are doing negative lookup then probing failure should be |
6295 // treated as a lookup success. For positive lookup probing failure | 6298 // treated as a lookup success. For positive lookup probing failure |
6296 // should be treated as lookup failure. | 6299 // should be treated as lookup failure. |
6297 if (mode_ == POSITIVE_LOOKUP) { | 6300 if (mode_ == POSITIVE_LOOKUP) { |
6298 __ movq(scratch, Immediate(0)); | 6301 __ movq(scratch, Immediate(0)); |
6299 __ Drop(1); | 6302 __ Drop(1); |
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6769 #endif | 6772 #endif |
6770 | 6773 |
6771 __ Ret(); | 6774 __ Ret(); |
6772 } | 6775 } |
6773 | 6776 |
6774 #undef __ | 6777 #undef __ |
6775 | 6778 |
6776 } } // namespace v8::internal | 6779 } } // namespace v8::internal |
6777 | 6780 |
6778 #endif // V8_TARGET_ARCH_X64 | 6781 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |