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