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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 __ j(equal, global_object); | 53 __ j(equal, global_object); |
54 __ cmp(type, JS_BUILTINS_OBJECT_TYPE); | 54 __ cmp(type, JS_BUILTINS_OBJECT_TYPE); |
55 __ j(equal, global_object); | 55 __ j(equal, global_object); |
56 __ cmp(type, JS_GLOBAL_PROXY_TYPE); | 56 __ cmp(type, JS_GLOBAL_PROXY_TYPE); |
57 __ j(equal, global_object); | 57 __ j(equal, global_object); |
58 } | 58 } |
59 | 59 |
60 | 60 |
61 // Generated code falls through if the receiver is a regular non-global | 61 // Generated code falls through if the receiver is a regular non-global |
62 // JS object with slow properties and no interceptors. | 62 // JS object with slow properties and no interceptors. |
63 static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm, | 63 static void GenerateNameDictionaryReceiverCheck(MacroAssembler* masm, |
64 Register receiver, | 64 Register receiver, |
65 Register r0, | 65 Register r0, |
66 Register r1, | 66 Register r1, |
67 Label* miss) { | 67 Label* miss) { |
68 // Register usage: | 68 // Register usage: |
69 // receiver: holds the receiver on entry and is unchanged. | 69 // receiver: holds the receiver on entry and is unchanged. |
70 // r0: used to hold receiver instance type. | 70 // r0: used to hold receiver instance type. |
71 // Holds the property dictionary on fall through. | 71 // Holds the property dictionary on fall through. |
72 // r1: used to hold receivers map. | 72 // r1: used to hold receivers map. |
73 | 73 |
74 // Check that the receiver isn't a smi. | 74 // Check that the receiver isn't a smi. |
75 __ JumpIfSmi(receiver, miss); | 75 __ JumpIfSmi(receiver, miss); |
76 | 76 |
77 // Check that the receiver is a valid JS object. | 77 // Check that the receiver is a valid JS object. |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 // | 120 // |
121 // r0 - used for the index into the property dictionary | 121 // r0 - used for the index into the property dictionary |
122 // | 122 // |
123 // r1 - used to hold the capacity of the property dictionary. | 123 // r1 - used to hold the capacity of the property dictionary. |
124 // | 124 // |
125 // result - holds the result on exit. | 125 // result - holds the result on exit. |
126 | 126 |
127 Label done; | 127 Label done; |
128 | 128 |
129 // Probe the dictionary. | 129 // Probe the dictionary. |
130 StringDictionaryLookupStub::GeneratePositiveLookup(masm, | 130 NameDictionaryLookupStub::GeneratePositiveLookup(masm, |
131 miss_label, | 131 miss_label, |
132 &done, | 132 &done, |
133 elements, | 133 elements, |
134 name, | 134 name, |
135 r0, | 135 r0, |
136 r1); | 136 r1); |
137 | 137 |
138 // If probing finds an entry in the dictionary, r0 contains the | 138 // If probing finds an entry in the dictionary, r0 contains the |
139 // index into the dictionary. Check that the value is a normal | 139 // index into the dictionary. Check that the value is a normal |
140 // property. | 140 // property. |
141 __ bind(&done); | 141 __ bind(&done); |
142 const int kElementsStartOffset = | 142 const int kElementsStartOffset = |
143 StringDictionary::kHeaderSize + | 143 NameDictionary::kHeaderSize + |
144 StringDictionary::kElementsStartIndex * kPointerSize; | 144 NameDictionary::kElementsStartIndex * kPointerSize; |
145 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; | 145 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; |
146 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag), | 146 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag), |
147 Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize)); | 147 Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize)); |
148 __ j(not_zero, miss_label); | 148 __ j(not_zero, miss_label); |
149 | 149 |
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 |
(...skipping 20 matching lines...) Expand all Loading... |
175 // | 175 // |
176 // value - holds the value to store and is unchanged. | 176 // value - holds the value to store and is unchanged. |
177 // | 177 // |
178 // r0 - used for index into the property dictionary and is clobbered. | 178 // r0 - used for index into the property dictionary and is clobbered. |
179 // | 179 // |
180 // r1 - used to hold the capacity of the property dictionary and is clobbered. | 180 // r1 - used to hold the capacity of the property dictionary and is clobbered. |
181 Label done; | 181 Label done; |
182 | 182 |
183 | 183 |
184 // Probe the dictionary. | 184 // Probe the dictionary. |
185 StringDictionaryLookupStub::GeneratePositiveLookup(masm, | 185 NameDictionaryLookupStub::GeneratePositiveLookup(masm, |
186 miss_label, | 186 miss_label, |
187 &done, | 187 &done, |
188 elements, | 188 elements, |
189 name, | 189 name, |
190 r0, | 190 r0, |
191 r1); | 191 r1); |
192 | 192 |
193 // If probing finds an entry in the dictionary, r0 contains the | 193 // If probing finds an entry in the dictionary, r0 contains the |
194 // index into the dictionary. Check that the value is a normal | 194 // index into the dictionary. Check that the value is a normal |
195 // property that is not read only. | 195 // property that is not read only. |
196 __ bind(&done); | 196 __ bind(&done); |
197 const int kElementsStartOffset = | 197 const int kElementsStartOffset = |
198 StringDictionary::kHeaderSize + | 198 NameDictionary::kHeaderSize + |
199 StringDictionary::kElementsStartIndex * kPointerSize; | 199 NameDictionary::kElementsStartIndex * kPointerSize; |
200 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; | 200 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; |
201 const int kTypeAndReadOnlyMask = | 201 const int kTypeAndReadOnlyMask = |
202 (PropertyDetails::TypeField::kMask | | 202 (PropertyDetails::TypeField::kMask | |
203 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize; | 203 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize; |
204 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag), | 204 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag), |
205 Immediate(kTypeAndReadOnlyMask)); | 205 Immediate(kTypeAndReadOnlyMask)); |
206 __ j(not_zero, miss_label); | 206 __ j(not_zero, miss_label); |
207 | 207 |
208 // Store the value at the masked, scaled index. | 208 // Store the value at the masked, scaled index. |
209 const int kValueOffset = kElementsStartOffset + kPointerSize; | 209 const int kValueOffset = kElementsStartOffset + kPointerSize; |
(...skipping 75 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 an internalized string. | 295 // Checks whether a key is an array index string or a unique name. |
296 // Falls through if the key is an internalized string. | 296 // Falls through if the key is a unique name. |
297 static void GenerateKeyStringCheck(MacroAssembler* masm, | 297 static void GenerateKeyNameCheck(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_internalized) { | 302 Label* not_unique) { |
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 Label unique; |
309 __ j(above_equal, not_internalized); | 309 __ CmpObjectType(key, LAST_UNIQUE_NAME_TYPE, map); |
| 310 __ j(above, not_unique); |
| 311 STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE); |
| 312 __ j(equal, &unique); |
310 | 313 |
311 // Is the string an array index, with cached numeric value? | 314 // Is the string an array index, with cached numeric value? |
312 __ mov(hash, FieldOperand(key, String::kHashFieldOffset)); | 315 __ mov(hash, FieldOperand(key, Name::kHashFieldOffset)); |
313 __ test(hash, Immediate(String::kContainsCachedArrayIndexMask)); | 316 __ test(hash, Immediate(Name::kContainsCachedArrayIndexMask)); |
314 __ j(zero, index_string); | 317 __ j(zero, index_string); |
315 | 318 |
316 // Is the string internalized? | 319 // Is the string internalized? |
317 STATIC_ASSERT(kInternalizedTag != 0); | 320 STATIC_ASSERT(kInternalizedTag != 0); |
318 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsInternalizedMask); | 321 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsInternalizedMask); |
319 __ j(zero, not_internalized); | 322 __ j(zero, not_unique); |
| 323 |
| 324 __ bind(&unique); |
320 } | 325 } |
321 | 326 |
322 | 327 |
323 static Operand GenerateMappedArgumentsLookup(MacroAssembler* masm, | 328 static Operand GenerateMappedArgumentsLookup(MacroAssembler* masm, |
324 Register object, | 329 Register object, |
325 Register key, | 330 Register key, |
326 Register scratch1, | 331 Register scratch1, |
327 Register scratch2, | 332 Register scratch2, |
328 Label* unmapped_case, | 333 Label* unmapped_case, |
329 Label* slow_case) { | 334 Label* slow_case) { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
396 FixedArray::kHeaderSize); | 401 FixedArray::kHeaderSize); |
397 } | 402 } |
398 | 403 |
399 | 404 |
400 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 405 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
401 // ----------- S t a t e ------------- | 406 // ----------- S t a t e ------------- |
402 // -- ecx : key | 407 // -- ecx : key |
403 // -- edx : receiver | 408 // -- edx : receiver |
404 // -- esp[0] : return address | 409 // -- esp[0] : return address |
405 // ----------------------------------- | 410 // ----------------------------------- |
406 Label slow, check_string, index_smi, index_string, property_array_property; | 411 Label slow, check_name, index_smi, index_name, property_array_property; |
407 Label probe_dictionary, check_number_dictionary; | 412 Label probe_dictionary, check_number_dictionary; |
408 | 413 |
409 // Check that the key is a smi. | 414 // Check that the key is a smi. |
410 __ JumpIfNotSmi(ecx, &check_string); | 415 __ JumpIfNotSmi(ecx, &check_name); |
411 __ bind(&index_smi); | 416 __ bind(&index_smi); |
412 // Now the key is known to be a smi. This place is also jumped to from | 417 // Now the key is known to be a smi. This place is also jumped to from |
413 // where a numeric string is converted to a smi. | 418 // where a numeric string is converted to a smi. |
414 | 419 |
415 GenerateKeyedLoadReceiverCheck( | 420 GenerateKeyedLoadReceiverCheck( |
416 masm, edx, eax, Map::kHasIndexedInterceptor, &slow); | 421 masm, edx, eax, Map::kHasIndexedInterceptor, &slow); |
417 | 422 |
418 // Check the receiver's map to see if it has fast elements. | 423 // Check the receiver's map to see if it has fast elements. |
419 __ CheckFastElements(eax, &check_number_dictionary); | 424 __ CheckFastElements(eax, &check_number_dictionary); |
420 | 425 |
(...skipping 30 matching lines...) Expand all Loading... |
451 // Pop the receiver from the stack and jump to runtime. | 456 // Pop the receiver from the stack and jump to runtime. |
452 __ pop(edx); | 457 __ pop(edx); |
453 | 458 |
454 __ bind(&slow); | 459 __ bind(&slow); |
455 // Slow case: jump to runtime. | 460 // Slow case: jump to runtime. |
456 // edx: receiver | 461 // edx: receiver |
457 // ecx: key | 462 // ecx: key |
458 __ IncrementCounter(counters->keyed_load_generic_slow(), 1); | 463 __ IncrementCounter(counters->keyed_load_generic_slow(), 1); |
459 GenerateRuntimeGetProperty(masm); | 464 GenerateRuntimeGetProperty(masm); |
460 | 465 |
461 __ bind(&check_string); | 466 __ bind(&check_name); |
462 GenerateKeyStringCheck(masm, ecx, eax, ebx, &index_string, &slow); | 467 GenerateKeyNameCheck(masm, ecx, eax, ebx, &index_name, &slow); |
463 | 468 |
464 GenerateKeyedLoadReceiverCheck( | 469 GenerateKeyedLoadReceiverCheck( |
465 masm, edx, eax, Map::kHasNamedInterceptor, &slow); | 470 masm, edx, eax, Map::kHasNamedInterceptor, &slow); |
466 | 471 |
467 // If the receiver is a fast-case object, check the keyed lookup | 472 // If the receiver is a fast-case object, check the keyed lookup |
468 // cache. Otherwise probe the dictionary. | 473 // cache. Otherwise probe the dictionary. |
469 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); | 474 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); |
470 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | 475 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
471 Immediate(isolate->factory()->hash_table_map())); | 476 Immediate(isolate->factory()->hash_table_map())); |
472 __ j(equal, &probe_dictionary); | 477 __ j(equal, &probe_dictionary); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
561 __ bind(&probe_dictionary); | 566 __ bind(&probe_dictionary); |
562 | 567 |
563 __ mov(eax, FieldOperand(edx, JSObject::kMapOffset)); | 568 __ mov(eax, FieldOperand(edx, JSObject::kMapOffset)); |
564 __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset)); | 569 __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset)); |
565 GenerateGlobalInstanceTypeCheck(masm, eax, &slow); | 570 GenerateGlobalInstanceTypeCheck(masm, eax, &slow); |
566 | 571 |
567 GenerateDictionaryLoad(masm, &slow, ebx, ecx, eax, edi, eax); | 572 GenerateDictionaryLoad(masm, &slow, ebx, ecx, eax, edi, eax); |
568 __ IncrementCounter(counters->keyed_load_generic_symbol(), 1); | 573 __ IncrementCounter(counters->keyed_load_generic_symbol(), 1); |
569 __ ret(0); | 574 __ ret(0); |
570 | 575 |
571 __ bind(&index_string); | 576 __ bind(&index_name); |
572 __ IndexFromHash(ebx, ecx); | 577 __ IndexFromHash(ebx, ecx); |
573 // Now jump to the place where smi keys are handled. | 578 // Now jump to the place where smi keys are handled. |
574 __ jmp(&index_smi); | 579 __ jmp(&index_smi); |
575 } | 580 } |
576 | 581 |
577 | 582 |
578 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 583 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
579 // ----------- S t a t e ------------- | 584 // ----------- S t a t e ------------- |
580 // -- ecx : key (index) | 585 // -- ecx : key (index) |
581 // -- edx : receiver | 586 // -- edx : receiver |
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1009 // -- esp[0] : return address | 1014 // -- esp[0] : return address |
1010 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1015 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1011 // -- ... | 1016 // -- ... |
1012 // -- esp[(argc + 1) * 4] : receiver | 1017 // -- esp[(argc + 1) * 4] : receiver |
1013 // ----------------------------------- | 1018 // ----------------------------------- |
1014 Label miss; | 1019 Label miss; |
1015 | 1020 |
1016 // Get the receiver of the function from the stack; 1 ~ return address. | 1021 // Get the receiver of the function from the stack; 1 ~ return address. |
1017 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1022 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1018 | 1023 |
1019 GenerateStringDictionaryReceiverCheck(masm, edx, eax, ebx, &miss); | 1024 GenerateNameDictionaryReceiverCheck(masm, edx, eax, ebx, &miss); |
1020 | 1025 |
1021 // eax: elements | 1026 // eax: elements |
1022 // Search the dictionary placing the result in edi. | 1027 // Search the dictionary placing the result in edi. |
1023 GenerateDictionaryLoad(masm, &miss, eax, ecx, edi, ebx, edi); | 1028 GenerateDictionaryLoad(masm, &miss, eax, ecx, edi, ebx, edi); |
1024 GenerateFunctionTailCall(masm, argc, &miss); | 1029 GenerateFunctionTailCall(masm, argc, &miss); |
1025 | 1030 |
1026 __ bind(&miss); | 1031 __ bind(&miss); |
1027 } | 1032 } |
1028 | 1033 |
1029 | 1034 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1125 // -- esp[0] : return address | 1130 // -- esp[0] : return address |
1126 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1131 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1127 // -- ... | 1132 // -- ... |
1128 // -- esp[(argc + 1) * 4] : receiver | 1133 // -- esp[(argc + 1) * 4] : receiver |
1129 // ----------------------------------- | 1134 // ----------------------------------- |
1130 | 1135 |
1131 // Get the receiver of the function from the stack; 1 ~ return address. | 1136 // Get the receiver of the function from the stack; 1 ~ return address. |
1132 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1137 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1133 | 1138 |
1134 Label do_call, slow_call, slow_load, slow_reload_receiver; | 1139 Label do_call, slow_call, slow_load, slow_reload_receiver; |
1135 Label check_number_dictionary, check_string, lookup_monomorphic_cache; | 1140 Label check_number_dictionary, check_name, lookup_monomorphic_cache; |
1136 Label index_smi, index_string; | 1141 Label index_smi, index_name; |
1137 | 1142 |
1138 // Check that the key is a smi. | 1143 // Check that the key is a smi. |
1139 __ JumpIfNotSmi(ecx, &check_string); | 1144 __ JumpIfNotSmi(ecx, &check_name); |
1140 | 1145 |
1141 __ bind(&index_smi); | 1146 __ bind(&index_smi); |
1142 // Now the key is known to be a smi. This place is also jumped to from | 1147 // Now the key is known to be a smi. This place is also jumped to from |
1143 // where a numeric string is converted to a smi. | 1148 // where a numeric string is converted to a smi. |
1144 | 1149 |
1145 GenerateKeyedLoadReceiverCheck( | 1150 GenerateKeyedLoadReceiverCheck( |
1146 masm, edx, eax, Map::kHasIndexedInterceptor, &slow_call); | 1151 masm, edx, eax, Map::kHasIndexedInterceptor, &slow_call); |
1147 | 1152 |
1148 GenerateFastArrayLoad( | 1153 GenerateFastArrayLoad( |
1149 masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load); | 1154 masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1188 __ push(edx); // pass the receiver | 1193 __ push(edx); // pass the receiver |
1189 __ push(ecx); // pass the key | 1194 __ push(ecx); // pass the key |
1190 __ CallRuntime(Runtime::kKeyedGetProperty, 2); | 1195 __ CallRuntime(Runtime::kKeyedGetProperty, 2); |
1191 __ pop(ecx); // restore the key | 1196 __ pop(ecx); // restore the key |
1192 // Leave the internal frame. | 1197 // Leave the internal frame. |
1193 } | 1198 } |
1194 | 1199 |
1195 __ mov(edi, eax); | 1200 __ mov(edi, eax); |
1196 __ jmp(&do_call); | 1201 __ jmp(&do_call); |
1197 | 1202 |
1198 __ bind(&check_string); | 1203 __ bind(&check_name); |
1199 GenerateKeyStringCheck(masm, ecx, eax, ebx, &index_string, &slow_call); | 1204 GenerateKeyNameCheck(masm, ecx, eax, ebx, &index_name, &slow_call); |
1200 | 1205 |
1201 // The key is known to be an internalized string. | 1206 // The key is known to be a unique name. |
1202 // If the receiver is a regular JS object with slow properties then do | 1207 // If the receiver is a regular JS object with slow properties then do |
1203 // a quick inline probe of the receiver's dictionary. | 1208 // a quick inline probe of the receiver's dictionary. |
1204 // Otherwise do the monomorphic cache probe. | 1209 // Otherwise do the monomorphic cache probe. |
1205 GenerateKeyedLoadReceiverCheck( | 1210 GenerateKeyedLoadReceiverCheck( |
1206 masm, edx, eax, Map::kHasNamedInterceptor, &lookup_monomorphic_cache); | 1211 masm, edx, eax, Map::kHasNamedInterceptor, &lookup_monomorphic_cache); |
1207 | 1212 |
1208 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); | 1213 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); |
1209 __ CheckMap(ebx, | 1214 __ CheckMap(ebx, |
1210 isolate->factory()->hash_table_map(), | 1215 isolate->factory()->hash_table_map(), |
1211 &lookup_monomorphic_cache, | 1216 &lookup_monomorphic_cache, |
1212 DONT_DO_SMI_CHECK); | 1217 DONT_DO_SMI_CHECK); |
1213 | 1218 |
1214 GenerateDictionaryLoad(masm, &slow_load, ebx, ecx, eax, edi, edi); | 1219 GenerateDictionaryLoad(masm, &slow_load, ebx, ecx, eax, edi, edi); |
1215 __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1); | 1220 __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1); |
1216 __ jmp(&do_call); | 1221 __ jmp(&do_call); |
1217 | 1222 |
1218 __ bind(&lookup_monomorphic_cache); | 1223 __ bind(&lookup_monomorphic_cache); |
1219 __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1); | 1224 __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1); |
1220 CallICBase::GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC, | 1225 CallICBase::GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC, |
1221 Code::kNoExtraICState); | 1226 Code::kNoExtraICState); |
1222 // Fall through on miss. | 1227 // Fall through on miss. |
1223 | 1228 |
1224 __ bind(&slow_call); | 1229 __ bind(&slow_call); |
1225 // This branch is taken if: | 1230 // This branch is taken if: |
1226 // - the receiver requires boxing or access check, | 1231 // - the receiver requires boxing or access check, |
1227 // - the key is neither smi nor an internalized string, | 1232 // - the key is neither smi nor a unique name, |
1228 // - the value loaded is not a function, | 1233 // - the value loaded is not a function, |
1229 // - there is hope that the runtime will create a monomorphic call stub | 1234 // - there is hope that the runtime will create a monomorphic call stub |
1230 // that will get fetched next time. | 1235 // that will get fetched next time. |
1231 __ IncrementCounter(counters->keyed_call_generic_slow(), 1); | 1236 __ IncrementCounter(counters->keyed_call_generic_slow(), 1); |
1232 GenerateMiss(masm, argc); | 1237 GenerateMiss(masm, argc); |
1233 | 1238 |
1234 __ bind(&index_string); | 1239 __ bind(&index_name); |
1235 __ IndexFromHash(ebx, ecx); | 1240 __ IndexFromHash(ebx, ecx); |
1236 // Now jump to the place where smi keys are handled. | 1241 // Now jump to the place where smi keys are handled. |
1237 __ jmp(&index_smi); | 1242 __ jmp(&index_smi); |
1238 } | 1243 } |
1239 | 1244 |
1240 | 1245 |
1241 void KeyedCallIC::GenerateNonStrictArguments(MacroAssembler* masm, | 1246 void KeyedCallIC::GenerateNonStrictArguments(MacroAssembler* masm, |
1242 int argc) { | 1247 int argc) { |
1243 // ----------- S t a t e ------------- | 1248 // ----------- S t a t e ------------- |
1244 // -- ecx : name | 1249 // -- ecx : name |
(...skipping 24 matching lines...) Expand all Loading... |
1269 | 1274 |
1270 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { | 1275 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { |
1271 // ----------- S t a t e ------------- | 1276 // ----------- S t a t e ------------- |
1272 // -- ecx : name | 1277 // -- ecx : name |
1273 // -- esp[0] : return address | 1278 // -- esp[0] : return address |
1274 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1279 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1275 // -- ... | 1280 // -- ... |
1276 // -- esp[(argc + 1) * 4] : receiver | 1281 // -- esp[(argc + 1) * 4] : receiver |
1277 // ----------------------------------- | 1282 // ----------------------------------- |
1278 | 1283 |
1279 // Check if the name is a string. | 1284 // Check if the name is really a name. |
1280 Label miss; | 1285 Label miss; |
1281 __ JumpIfSmi(ecx, &miss); | 1286 __ JumpIfSmi(ecx, &miss); |
1282 Condition cond = masm->IsObjectStringType(ecx, eax, eax); | 1287 Condition cond = masm->IsObjectNameType(ecx, eax, eax); |
1283 __ j(NegateCondition(cond), &miss); | 1288 __ j(NegateCondition(cond), &miss); |
1284 CallICBase::GenerateNormal(masm, argc); | 1289 CallICBase::GenerateNormal(masm, argc); |
1285 __ bind(&miss); | 1290 __ bind(&miss); |
1286 GenerateMiss(masm, argc); | 1291 GenerateMiss(masm, argc); |
1287 } | 1292 } |
1288 | 1293 |
1289 | 1294 |
1290 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { | 1295 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
1291 // ----------- S t a t e ------------- | 1296 // ----------- S t a t e ------------- |
1292 // -- ecx : name | 1297 // -- ecx : name |
(...skipping 12 matching lines...) Expand all Loading... |
1305 | 1310 |
1306 | 1311 |
1307 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 1312 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
1308 // ----------- S t a t e ------------- | 1313 // ----------- S t a t e ------------- |
1309 // -- ecx : name | 1314 // -- ecx : name |
1310 // -- edx : receiver | 1315 // -- edx : receiver |
1311 // -- esp[0] : return address | 1316 // -- esp[0] : return address |
1312 // ----------------------------------- | 1317 // ----------------------------------- |
1313 Label miss; | 1318 Label miss; |
1314 | 1319 |
1315 GenerateStringDictionaryReceiverCheck(masm, edx, eax, ebx, &miss); | 1320 GenerateNameDictionaryReceiverCheck(masm, edx, eax, ebx, &miss); |
1316 | 1321 |
1317 // eax: elements | 1322 // eax: elements |
1318 // Search the dictionary placing the result in eax. | 1323 // Search the dictionary placing the result in eax. |
1319 GenerateDictionaryLoad(masm, &miss, eax, ecx, edi, ebx, eax); | 1324 GenerateDictionaryLoad(masm, &miss, eax, ecx, edi, ebx, eax); |
1320 __ ret(0); | 1325 __ ret(0); |
1321 | 1326 |
1322 // Cache miss: Jump to runtime. | 1327 // Cache miss: Jump to runtime. |
1323 __ bind(&miss); | 1328 __ bind(&miss); |
1324 GenerateMiss(masm); | 1329 GenerateMiss(masm); |
1325 } | 1330 } |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1429 void StoreIC::GenerateNormal(MacroAssembler* masm) { | 1434 void StoreIC::GenerateNormal(MacroAssembler* masm) { |
1430 // ----------- S t a t e ------------- | 1435 // ----------- S t a t e ------------- |
1431 // -- eax : value | 1436 // -- eax : value |
1432 // -- ecx : name | 1437 // -- ecx : name |
1433 // -- edx : receiver | 1438 // -- edx : receiver |
1434 // -- esp[0] : return address | 1439 // -- esp[0] : return address |
1435 // ----------------------------------- | 1440 // ----------------------------------- |
1436 | 1441 |
1437 Label miss, restore_miss; | 1442 Label miss, restore_miss; |
1438 | 1443 |
1439 GenerateStringDictionaryReceiverCheck(masm, edx, ebx, edi, &miss); | 1444 GenerateNameDictionaryReceiverCheck(masm, edx, ebx, edi, &miss); |
1440 | 1445 |
1441 // A lot of registers are needed for storing to slow case | 1446 // A lot of registers are needed for storing to slow case |
1442 // objects. Push and restore receiver but rely on | 1447 // objects. Push and restore receiver but rely on |
1443 // GenerateDictionaryStore preserving the value and name. | 1448 // GenerateDictionaryStore preserving the value and name. |
1444 __ push(edx); | 1449 __ push(edx); |
1445 GenerateDictionaryStore(masm, &restore_miss, ebx, ecx, eax, edx, edi); | 1450 GenerateDictionaryStore(masm, &restore_miss, ebx, ecx, eax, edx, edi); |
1446 __ Drop(1); | 1451 __ Drop(1); |
1447 Counters* counters = masm->isolate()->counters(); | 1452 Counters* counters = masm->isolate()->counters(); |
1448 __ IncrementCounter(counters->store_normal_hit(), 1); | 1453 __ IncrementCounter(counters->store_normal_hit(), 1); |
1449 __ ret(0); | 1454 __ ret(0); |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1665 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) | 1670 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) |
1666 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 1671 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
1667 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 1672 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
1668 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1673 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
1669 } | 1674 } |
1670 | 1675 |
1671 | 1676 |
1672 } } // namespace v8::internal | 1677 } } // namespace v8::internal |
1673 | 1678 |
1674 #endif // V8_TARGET_ARCH_IA32 | 1679 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |