| 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 |