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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 | 93 |
94 __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 94 __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
95 __ CheckMap(r0, FACTORY->hash_table_map(), miss, DONT_DO_SMI_CHECK); | 95 __ CheckMap(r0, FACTORY->hash_table_map(), miss, DONT_DO_SMI_CHECK); |
96 } | 96 } |
97 | 97 |
98 | 98 |
99 // Helper function used to load a property from a dictionary backing | 99 // Helper function used to load a property from a dictionary backing |
100 // storage. This function may fail to load a property even though it is | 100 // storage. This function may fail to load a property even though it is |
101 // in the dictionary, so code at miss_label must always call a backup | 101 // in the dictionary, so code at miss_label must always call a backup |
102 // property load that is complete. This function is safe to call if | 102 // property load that is complete. This function is safe to call if |
103 // name is not a symbol, and will jump to the miss_label in that | 103 // name is not internalized, and will jump to the miss_label in that |
104 // case. The generated code assumes that the receiver has slow | 104 // case. The generated code assumes that the receiver has slow |
105 // properties, is not a global object and does not have interceptors. | 105 // properties, is not a global object and does not have interceptors. |
106 static void GenerateDictionaryLoad(MacroAssembler* masm, | 106 static void GenerateDictionaryLoad(MacroAssembler* masm, |
107 Label* miss_label, | 107 Label* miss_label, |
108 Register elements, | 108 Register elements, |
109 Register name, | 109 Register name, |
110 Register r0, | 110 Register r0, |
111 Register r1, | 111 Register r1, |
112 Register result) { | 112 Register result) { |
113 // Register use: | 113 // Register use: |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 // Get the value at the masked, scaled index. | 150 // Get the value at the masked, scaled index. |
151 const int kValueOffset = kElementsStartOffset + kPointerSize; | 151 const int kValueOffset = kElementsStartOffset + kPointerSize; |
152 __ mov(result, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); | 152 __ mov(result, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); |
153 } | 153 } |
154 | 154 |
155 | 155 |
156 // Helper function used to store a property to a dictionary backing | 156 // Helper function used to store a property to a dictionary backing |
157 // storage. This function may fail to store a property eventhough it | 157 // storage. This function may fail to store a property eventhough it |
158 // is in the dictionary, so code at miss_label must always call a | 158 // is in the dictionary, so code at miss_label must always call a |
159 // backup property store that is complete. This function is safe to | 159 // backup property store that is complete. This function is safe to |
160 // call if name is not a symbol, and will jump to the miss_label in | 160 // call if name is not internalized, and will jump to the miss_label in |
161 // that case. The generated code assumes that the receiver has slow | 161 // that case. The generated code assumes that the receiver has slow |
162 // properties, is not a global object and does not have interceptors. | 162 // properties, is not a global object and does not have interceptors. |
163 static void GenerateDictionaryStore(MacroAssembler* masm, | 163 static void GenerateDictionaryStore(MacroAssembler* masm, |
164 Label* miss_label, | 164 Label* miss_label, |
165 Register elements, | 165 Register elements, |
166 Register name, | 166 Register name, |
167 Register value, | 167 Register value, |
168 Register r0, | 168 Register r0, |
169 Register r1) { | 169 Register r1) { |
170 // Register use: | 170 // Register use: |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 __ cmp(scratch, Immediate(FACTORY->the_hole_value())); | 285 __ cmp(scratch, Immediate(FACTORY->the_hole_value())); |
286 // In case the loaded value is the_hole we have to consult GetProperty | 286 // In case the loaded value is the_hole we have to consult GetProperty |
287 // to ensure the prototype chain is searched. | 287 // to ensure the prototype chain is searched. |
288 __ j(equal, out_of_range); | 288 __ j(equal, out_of_range); |
289 if (!result.is(scratch)) { | 289 if (!result.is(scratch)) { |
290 __ mov(result, scratch); | 290 __ mov(result, scratch); |
291 } | 291 } |
292 } | 292 } |
293 | 293 |
294 | 294 |
295 // Checks whether a key is an array index string or a symbol string. | 295 // Checks whether a key is an array index string or an internalized string. |
296 // Falls through if the key is a symbol. | 296 // Falls through if the key is an internalized string. |
297 static void GenerateKeyStringCheck(MacroAssembler* masm, | 297 static void GenerateKeyStringCheck(MacroAssembler* masm, |
298 Register key, | 298 Register key, |
299 Register map, | 299 Register map, |
300 Register hash, | 300 Register hash, |
301 Label* index_string, | 301 Label* index_string, |
302 Label* not_symbol) { | 302 Label* not_internalized) { |
303 // Register use: | 303 // Register use: |
304 // key - holds the key and is unchanged. Assumed to be non-smi. | 304 // key - holds the key and is unchanged. Assumed to be non-smi. |
305 // Scratch registers: | 305 // Scratch registers: |
306 // map - used to hold the map of the key. | 306 // map - used to hold the map of the key. |
307 // hash - used to hold the hash of the key. | 307 // hash - used to hold the hash of the key. |
308 __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map); | 308 __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map); |
309 __ j(above_equal, not_symbol); | 309 __ j(above_equal, not_internalized); |
310 | 310 |
311 // Is the string an array index, with cached numeric value? | 311 // Is the string an array index, with cached numeric value? |
312 __ mov(hash, FieldOperand(key, String::kHashFieldOffset)); | 312 __ mov(hash, FieldOperand(key, String::kHashFieldOffset)); |
313 __ test(hash, Immediate(String::kContainsCachedArrayIndexMask)); | 313 __ test(hash, Immediate(String::kContainsCachedArrayIndexMask)); |
314 __ j(zero, index_string); | 314 __ j(zero, index_string); |
315 | 315 |
316 // Is the string a symbol? | 316 // Is the string internalized? |
317 STATIC_ASSERT(kSymbolTag != 0); | 317 STATIC_ASSERT(kInternalizedTag != 0); |
318 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask); | 318 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsInternalizedMask); |
319 __ j(zero, not_symbol); | 319 __ j(zero, not_internalized); |
320 } | 320 } |
321 | 321 |
322 | 322 |
323 static Operand GenerateMappedArgumentsLookup(MacroAssembler* masm, | 323 static Operand GenerateMappedArgumentsLookup(MacroAssembler* masm, |
324 Register object, | 324 Register object, |
325 Register key, | 325 Register key, |
326 Register scratch1, | 326 Register scratch1, |
327 Register scratch2, | 327 Register scratch2, |
328 Label* unmapped_case, | 328 Label* unmapped_case, |
329 Label* slow_case) { | 329 Label* slow_case) { |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
477 __ cmp(eax, FieldOperand(edx, HeapObject::kMapOffset)); | 477 __ cmp(eax, FieldOperand(edx, HeapObject::kMapOffset)); |
478 __ Check(equal, "Map is no longer in eax."); | 478 __ Check(equal, "Map is no longer in eax."); |
479 } | 479 } |
480 __ mov(ebx, eax); // Keep the map around for later. | 480 __ mov(ebx, eax); // Keep the map around for later. |
481 __ shr(eax, KeyedLookupCache::kMapHashShift); | 481 __ shr(eax, KeyedLookupCache::kMapHashShift); |
482 __ mov(edi, FieldOperand(ecx, String::kHashFieldOffset)); | 482 __ mov(edi, FieldOperand(ecx, String::kHashFieldOffset)); |
483 __ shr(edi, String::kHashShift); | 483 __ shr(edi, String::kHashShift); |
484 __ xor_(eax, edi); | 484 __ xor_(eax, edi); |
485 __ and_(eax, KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask); | 485 __ and_(eax, KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask); |
486 | 486 |
487 // Load the key (consisting of map and symbol) from the cache and | 487 // Load the key (consisting of map and internalized string) from the cache and |
488 // check for match. | 488 // check for match. |
489 Label load_in_object_property; | 489 Label load_in_object_property; |
490 static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket; | 490 static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket; |
491 Label hit_on_nth_entry[kEntriesPerBucket]; | 491 Label hit_on_nth_entry[kEntriesPerBucket]; |
492 ExternalReference cache_keys = | 492 ExternalReference cache_keys = |
493 ExternalReference::keyed_lookup_cache_keys(masm->isolate()); | 493 ExternalReference::keyed_lookup_cache_keys(masm->isolate()); |
494 | 494 |
495 for (int i = 0; i < kEntriesPerBucket - 1; i++) { | 495 for (int i = 0; i < kEntriesPerBucket - 1; i++) { |
496 Label try_next_entry; | 496 Label try_next_entry; |
497 __ mov(edi, eax); | 497 __ mov(edi, eax); |
(...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1191 __ pop(ecx); // restore the key | 1191 __ pop(ecx); // restore the key |
1192 // Leave the internal frame. | 1192 // Leave the internal frame. |
1193 } | 1193 } |
1194 | 1194 |
1195 __ mov(edi, eax); | 1195 __ mov(edi, eax); |
1196 __ jmp(&do_call); | 1196 __ jmp(&do_call); |
1197 | 1197 |
1198 __ bind(&check_string); | 1198 __ bind(&check_string); |
1199 GenerateKeyStringCheck(masm, ecx, eax, ebx, &index_string, &slow_call); | 1199 GenerateKeyStringCheck(masm, ecx, eax, ebx, &index_string, &slow_call); |
1200 | 1200 |
1201 // The key is known to be a symbol. | 1201 // The key is known to be an internalized string. |
1202 // If the receiver is a regular JS object with slow properties then do | 1202 // If the receiver is a regular JS object with slow properties then do |
1203 // a quick inline probe of the receiver's dictionary. | 1203 // a quick inline probe of the receiver's dictionary. |
1204 // Otherwise do the monomorphic cache probe. | 1204 // Otherwise do the monomorphic cache probe. |
1205 GenerateKeyedLoadReceiverCheck( | 1205 GenerateKeyedLoadReceiverCheck( |
1206 masm, edx, eax, Map::kHasNamedInterceptor, &lookup_monomorphic_cache); | 1206 masm, edx, eax, Map::kHasNamedInterceptor, &lookup_monomorphic_cache); |
1207 | 1207 |
1208 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); | 1208 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); |
1209 __ CheckMap(ebx, | 1209 __ CheckMap(ebx, |
1210 isolate->factory()->hash_table_map(), | 1210 isolate->factory()->hash_table_map(), |
1211 &lookup_monomorphic_cache, | 1211 &lookup_monomorphic_cache, |
1212 DONT_DO_SMI_CHECK); | 1212 DONT_DO_SMI_CHECK); |
1213 | 1213 |
1214 GenerateDictionaryLoad(masm, &slow_load, ebx, ecx, eax, edi, edi); | 1214 GenerateDictionaryLoad(masm, &slow_load, ebx, ecx, eax, edi, edi); |
1215 __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1); | 1215 __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1); |
1216 __ jmp(&do_call); | 1216 __ jmp(&do_call); |
1217 | 1217 |
1218 __ bind(&lookup_monomorphic_cache); | 1218 __ bind(&lookup_monomorphic_cache); |
1219 __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1); | 1219 __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1); |
1220 CallICBase::GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC, | 1220 CallICBase::GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC, |
1221 Code::kNoExtraICState); | 1221 Code::kNoExtraICState); |
1222 // Fall through on miss. | 1222 // Fall through on miss. |
1223 | 1223 |
1224 __ bind(&slow_call); | 1224 __ bind(&slow_call); |
1225 // This branch is taken if: | 1225 // This branch is taken if: |
1226 // - the receiver requires boxing or access check, | 1226 // - the receiver requires boxing or access check, |
1227 // - the key is neither smi nor symbol, | 1227 // - the key is neither smi nor an internalized string, |
1228 // - the value loaded is not a function, | 1228 // - the value loaded is not a function, |
1229 // - there is hope that the runtime will create a monomorphic call stub | 1229 // - there is hope that the runtime will create a monomorphic call stub |
1230 // that will get fetched next time. | 1230 // that will get fetched next time. |
1231 __ IncrementCounter(counters->keyed_call_generic_slow(), 1); | 1231 __ IncrementCounter(counters->keyed_call_generic_slow(), 1); |
1232 GenerateMiss(masm, argc); | 1232 GenerateMiss(masm, argc); |
1233 | 1233 |
1234 __ bind(&index_string); | 1234 __ bind(&index_string); |
1235 __ IndexFromHash(ebx, ecx); | 1235 __ IndexFromHash(ebx, ecx); |
1236 // Now jump to the place where smi keys are handled. | 1236 // Now jump to the place where smi keys are handled. |
1237 __ jmp(&index_smi); | 1237 __ jmp(&index_smi); |
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1665 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) | 1665 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) |
1666 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 1666 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
1667 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 1667 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
1668 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1668 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
1669 } | 1669 } |
1670 | 1670 |
1671 | 1671 |
1672 } } // namespace v8::internal | 1672 } } // namespace v8::internal |
1673 | 1673 |
1674 #endif // V8_TARGET_ARCH_IA32 | 1674 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |