| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 | 43 |
| 44 #define __ ACCESS_MASM(masm) | 44 #define __ ACCESS_MASM(masm) |
| 45 | 45 |
| 46 | 46 |
| 47 static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, | 47 static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, |
| 48 Register type, | 48 Register type, |
| 49 Label* global_object) { | 49 Label* global_object) { |
| 50 // Register usage: | 50 // Register usage: |
| 51 // type: holds the receiver instance type on entry. | 51 // type: holds the receiver instance type on entry. |
| 52 __ cmp(type, JS_GLOBAL_OBJECT_TYPE); | 52 __ cmp(type, JS_GLOBAL_OBJECT_TYPE); |
| 53 __ j(equal, global_object, not_taken); | 53 __ j(equal, global_object, Label::kFar, not_taken); |
| 54 __ cmp(type, JS_BUILTINS_OBJECT_TYPE); | 54 __ cmp(type, JS_BUILTINS_OBJECT_TYPE); |
| 55 __ j(equal, global_object, not_taken); | 55 __ j(equal, global_object, Label::kFar, not_taken); |
| 56 __ cmp(type, JS_GLOBAL_PROXY_TYPE); | 56 __ cmp(type, JS_GLOBAL_PROXY_TYPE); |
| 57 __ j(equal, global_object, not_taken); | 57 __ j(equal, global_object, Label::kFar, not_taken); |
| 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 GenerateStringDictionaryReceiverCheck(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 __ test(receiver, Immediate(kSmiTagMask)); | 75 __ test(receiver, Immediate(kSmiTagMask)); |
| 76 __ j(zero, miss, not_taken); | 76 __ j(zero, miss, Label::kFar, not_taken); |
| 77 | 77 |
| 78 // Check that the receiver is a valid JS object. | 78 // Check that the receiver is a valid JS object. |
| 79 __ mov(r1, FieldOperand(receiver, HeapObject::kMapOffset)); | 79 __ mov(r1, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 80 __ movzx_b(r0, FieldOperand(r1, Map::kInstanceTypeOffset)); | 80 __ movzx_b(r0, FieldOperand(r1, Map::kInstanceTypeOffset)); |
| 81 __ cmp(r0, FIRST_JS_OBJECT_TYPE); | 81 __ cmp(r0, FIRST_JS_OBJECT_TYPE); |
| 82 __ j(below, miss, not_taken); | 82 __ j(below, miss, Label::kFar, not_taken); |
| 83 | 83 |
| 84 // If this assert fails, we have to check upper bound too. | 84 // If this assert fails, we have to check upper bound too. |
| 85 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); | 85 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); |
| 86 | 86 |
| 87 GenerateGlobalInstanceTypeCheck(masm, r0, miss); | 87 GenerateGlobalInstanceTypeCheck(masm, r0, miss); |
| 88 | 88 |
| 89 // Check for non-global object that requires access check. | 89 // Check for non-global object that requires access check. |
| 90 __ test_b(FieldOperand(r1, Map::kBitFieldOffset), | 90 __ test_b(FieldOperand(r1, Map::kBitFieldOffset), |
| 91 (1 << Map::kIsAccessCheckNeeded) | | 91 (1 << Map::kIsAccessCheckNeeded) | |
| 92 (1 << Map::kHasNamedInterceptor)); | 92 (1 << Map::kHasNamedInterceptor)); |
| 93 __ j(not_zero, miss, not_taken); | 93 __ j(not_zero, miss, Label::kFar, not_taken); |
| 94 | 94 |
| 95 __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 95 __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
| 96 __ CheckMap(r0, FACTORY->hash_table_map(), miss, true); | 96 __ CheckMap(r0, FACTORY->hash_table_map(), miss, true); |
| 97 } | 97 } |
| 98 | 98 |
| 99 | 99 |
| 100 | |
| 101 // Helper function used to load a property from a dictionary backing | 100 // Helper function used to load a property from a dictionary backing |
| 102 // storage. This function may fail to load a property even though it is | 101 // storage. This function may fail to load a property even though it is |
| 103 // in the dictionary, so code at miss_label must always call a backup | 102 // in the dictionary, so code at miss_label must always call a backup |
| 104 // property load that is complete. This function is safe to call if | 103 // property load that is complete. This function is safe to call if |
| 105 // name is not a symbol, and will jump to the miss_label in that | 104 // name is not a symbol, and will jump to the miss_label in that |
| 106 // case. The generated code assumes that the receiver has slow | 105 // case. The generated code assumes that the receiver has slow |
| 107 // properties, is not a global object and does not have interceptors. | 106 // properties, is not a global object and does not have interceptors. |
| 108 static void GenerateDictionaryLoad(MacroAssembler* masm, | 107 static void GenerateDictionaryLoad(MacroAssembler* masm, |
| 109 Label* miss_label, | 108 Label* miss_label, |
| 110 Register elements, | 109 Register elements, |
| (...skipping 29 matching lines...) Expand all Loading... |
| 140 // If probing finds an entry in the dictionary, r0 contains the | 139 // If probing finds an entry in the dictionary, r0 contains the |
| 141 // index into the dictionary. Check that the value is a normal | 140 // index into the dictionary. Check that the value is a normal |
| 142 // property. | 141 // property. |
| 143 __ bind(&done); | 142 __ bind(&done); |
| 144 const int kElementsStartOffset = | 143 const int kElementsStartOffset = |
| 145 StringDictionary::kHeaderSize + | 144 StringDictionary::kHeaderSize + |
| 146 StringDictionary::kElementsStartIndex * kPointerSize; | 145 StringDictionary::kElementsStartIndex * kPointerSize; |
| 147 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; | 146 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; |
| 148 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag), | 147 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag), |
| 149 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); | 148 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); |
| 150 __ j(not_zero, miss_label, not_taken); | 149 __ j(not_zero, miss_label, Label::kFar, not_taken); |
| 151 | 150 |
| 152 // Get the value at the masked, scaled index. | 151 // Get the value at the masked, scaled index. |
| 153 const int kValueOffset = kElementsStartOffset + kPointerSize; | 152 const int kValueOffset = kElementsStartOffset + kPointerSize; |
| 154 __ mov(result, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); | 153 __ mov(result, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); |
| 155 } | 154 } |
| 156 | 155 |
| 157 | 156 |
| 158 // Helper function used to store a property to a dictionary backing | 157 // Helper function used to store a property to a dictionary backing |
| 159 // storage. This function may fail to store a property eventhough it | 158 // storage. This function may fail to store a property eventhough it |
| 160 // is in the dictionary, so code at miss_label must always call a | 159 // is in the dictionary, so code at miss_label must always call a |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 __ bind(&done); | 197 __ bind(&done); |
| 199 const int kElementsStartOffset = | 198 const int kElementsStartOffset = |
| 200 StringDictionary::kHeaderSize + | 199 StringDictionary::kHeaderSize + |
| 201 StringDictionary::kElementsStartIndex * kPointerSize; | 200 StringDictionary::kElementsStartIndex * kPointerSize; |
| 202 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; | 201 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; |
| 203 const int kTypeAndReadOnlyMask | 202 const int kTypeAndReadOnlyMask |
| 204 = (PropertyDetails::TypeField::mask() | | 203 = (PropertyDetails::TypeField::mask() | |
| 205 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize; | 204 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize; |
| 206 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag), | 205 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag), |
| 207 Immediate(kTypeAndReadOnlyMask)); | 206 Immediate(kTypeAndReadOnlyMask)); |
| 208 __ j(not_zero, miss_label, not_taken); | 207 __ j(not_zero, miss_label, Label::kFar, not_taken); |
| 209 | 208 |
| 210 // Store the value at the masked, scaled index. | 209 // Store the value at the masked, scaled index. |
| 211 const int kValueOffset = kElementsStartOffset + kPointerSize; | 210 const int kValueOffset = kElementsStartOffset + kPointerSize; |
| 212 __ lea(r0, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); | 211 __ lea(r0, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); |
| 213 __ mov(Operand(r0, 0), value); | 212 __ mov(Operand(r0, 0), value); |
| 214 | 213 |
| 215 // Update write barrier. Make sure not to clobber the value. | 214 // Update write barrier. Make sure not to clobber the value. |
| 216 __ mov(r1, value); | 215 __ mov(r1, value); |
| 217 __ RecordWrite(elements, r0, r1); | 216 __ RecordWrite(elements, r0, r1); |
| 218 } | 217 } |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 // Scale the index by multiplying by the entry size. | 287 // Scale the index by multiplying by the entry size. |
| 289 ASSERT(NumberDictionary::kEntrySize == 3); | 288 ASSERT(NumberDictionary::kEntrySize == 3); |
| 290 __ lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 | 289 __ lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 |
| 291 | 290 |
| 292 // Check if the key matches. | 291 // Check if the key matches. |
| 293 __ cmp(key, FieldOperand(elements, | 292 __ cmp(key, FieldOperand(elements, |
| 294 r2, | 293 r2, |
| 295 times_pointer_size, | 294 times_pointer_size, |
| 296 NumberDictionary::kElementsStartOffset)); | 295 NumberDictionary::kElementsStartOffset)); |
| 297 if (i != (kProbes - 1)) { | 296 if (i != (kProbes - 1)) { |
| 298 __ j(equal, &done, taken); | 297 __ j(equal, &done, Label::kFar, taken); |
| 299 } else { | 298 } else { |
| 300 __ j(not_equal, miss, not_taken); | 299 __ j(not_equal, miss, Label::kFar, not_taken); |
| 301 } | 300 } |
| 302 } | 301 } |
| 303 | 302 |
| 304 __ bind(&done); | 303 __ bind(&done); |
| 305 // Check that the value is a normal propety. | 304 // Check that the value is a normal propety. |
| 306 const int kDetailsOffset = | 305 const int kDetailsOffset = |
| 307 NumberDictionary::kElementsStartOffset + 2 * kPointerSize; | 306 NumberDictionary::kElementsStartOffset + 2 * kPointerSize; |
| 308 ASSERT_EQ(NORMAL, 0); | 307 ASSERT_EQ(NORMAL, 0); |
| 309 __ test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), | 308 __ test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), |
| 310 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); | 309 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 Register map, | 367 Register map, |
| 369 int interceptor_bit, | 368 int interceptor_bit, |
| 370 Label* slow) { | 369 Label* slow) { |
| 371 // Register use: | 370 // Register use: |
| 372 // receiver - holds the receiver and is unchanged. | 371 // receiver - holds the receiver and is unchanged. |
| 373 // Scratch registers: | 372 // Scratch registers: |
| 374 // map - used to hold the map of the receiver. | 373 // map - used to hold the map of the receiver. |
| 375 | 374 |
| 376 // Check that the object isn't a smi. | 375 // Check that the object isn't a smi. |
| 377 __ test(receiver, Immediate(kSmiTagMask)); | 376 __ test(receiver, Immediate(kSmiTagMask)); |
| 378 __ j(zero, slow, not_taken); | 377 __ j(zero, slow, Label::kFar, not_taken); |
| 379 | 378 |
| 380 // Get the map of the receiver. | 379 // Get the map of the receiver. |
| 381 __ mov(map, FieldOperand(receiver, HeapObject::kMapOffset)); | 380 __ mov(map, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 382 | 381 |
| 383 // Check bit field. | 382 // Check bit field. |
| 384 __ test_b(FieldOperand(map, Map::kBitFieldOffset), | 383 __ test_b(FieldOperand(map, Map::kBitFieldOffset), |
| 385 (1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit)); | 384 (1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit)); |
| 386 __ j(not_zero, slow, not_taken); | 385 __ j(not_zero, slow, Label::kFar, not_taken); |
| 387 // Check that the object is some kind of JS object EXCEPT JS Value type. | 386 // Check that the object is some kind of JS object EXCEPT JS Value type. |
| 388 // In the case that the object is a value-wrapper object, | 387 // In the case that the object is a value-wrapper object, |
| 389 // we enter the runtime system to make sure that indexing | 388 // we enter the runtime system to make sure that indexing |
| 390 // into string objects works as intended. | 389 // into string objects works as intended. |
| 391 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); | 390 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); |
| 392 | 391 |
| 393 __ CmpInstanceType(map, JS_OBJECT_TYPE); | 392 __ CmpInstanceType(map, JS_OBJECT_TYPE); |
| 394 __ j(below, slow, not_taken); | 393 __ j(below, slow, Label::kFar, not_taken); |
| 395 } | 394 } |
| 396 | 395 |
| 397 | 396 |
| 398 // Loads an indexed element from a fast case array. | 397 // Loads an indexed element from a fast case array. |
| 399 // If not_fast_array is NULL, doesn't perform the elements map check. | 398 // If not_fast_array is NULL, doesn't perform the elements map check. |
| 400 static void GenerateFastArrayLoad(MacroAssembler* masm, | 399 static void GenerateFastArrayLoad(MacroAssembler* masm, |
| 401 Register receiver, | 400 Register receiver, |
| 402 Register key, | 401 Register key, |
| 403 Register scratch, | 402 Register scratch, |
| 404 Register result, | 403 Register result, |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 447 // key - holds the key and is unchanged. Assumed to be non-smi. | 446 // key - holds the key and is unchanged. Assumed to be non-smi. |
| 448 // Scratch registers: | 447 // Scratch registers: |
| 449 // map - used to hold the map of the key. | 448 // map - used to hold the map of the key. |
| 450 // hash - used to hold the hash of the key. | 449 // hash - used to hold the hash of the key. |
| 451 __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map); | 450 __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map); |
| 452 __ j(above_equal, not_symbol); | 451 __ j(above_equal, not_symbol); |
| 453 | 452 |
| 454 // Is the string an array index, with cached numeric value? | 453 // Is the string an array index, with cached numeric value? |
| 455 __ mov(hash, FieldOperand(key, String::kHashFieldOffset)); | 454 __ mov(hash, FieldOperand(key, String::kHashFieldOffset)); |
| 456 __ test(hash, Immediate(String::kContainsCachedArrayIndexMask)); | 455 __ test(hash, Immediate(String::kContainsCachedArrayIndexMask)); |
| 457 __ j(zero, index_string, not_taken); | 456 __ j(zero, index_string, Label::kFar, not_taken); |
| 458 | 457 |
| 459 // Is the string a symbol? | 458 // Is the string a symbol? |
| 460 ASSERT(kSymbolTag != 0); | 459 ASSERT(kSymbolTag != 0); |
| 461 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask); | 460 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask); |
| 462 __ j(zero, not_symbol, not_taken); | 461 __ j(zero, not_symbol, Label::kFar, not_taken); |
| 463 } | 462 } |
| 464 | 463 |
| 465 | 464 |
| 466 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 465 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
| 467 // ----------- S t a t e ------------- | 466 // ----------- S t a t e ------------- |
| 468 // -- eax : key | 467 // -- eax : key |
| 469 // -- edx : receiver | 468 // -- edx : receiver |
| 470 // -- esp[0] : return address | 469 // -- esp[0] : return address |
| 471 // ----------------------------------- | 470 // ----------------------------------- |
| 472 Label slow, check_string, index_smi, index_string, property_array_property; | 471 Label slow, check_string, index_smi, index_string, property_array_property; |
| 473 Label probe_dictionary, check_number_dictionary; | 472 Label probe_dictionary, check_number_dictionary; |
| 474 | 473 |
| 475 // Check that the key is a smi. | 474 // Check that the key is a smi. |
| 476 __ test(eax, Immediate(kSmiTagMask)); | 475 __ test(eax, Immediate(kSmiTagMask)); |
| 477 __ j(not_zero, &check_string, not_taken); | 476 __ j(not_zero, &check_string, Label::kFar, not_taken); |
| 478 __ bind(&index_smi); | 477 __ bind(&index_smi); |
| 479 // Now the key is known to be a smi. This place is also jumped to from | 478 // Now the key is known to be a smi. This place is also jumped to from |
| 480 // where a numeric string is converted to a smi. | 479 // where a numeric string is converted to a smi. |
| 481 | 480 |
| 482 GenerateKeyedLoadReceiverCheck( | 481 GenerateKeyedLoadReceiverCheck( |
| 483 masm, edx, ecx, Map::kHasIndexedInterceptor, &slow); | 482 masm, edx, ecx, Map::kHasIndexedInterceptor, &slow); |
| 484 | 483 |
| 485 // Check the "has fast elements" bit in the receiver's map which is | 484 // Check the "has fast elements" bit in the receiver's map which is |
| 486 // now in ecx. | 485 // now in ecx. |
| 487 __ test_b(FieldOperand(ecx, Map::kBitField2Offset), | 486 __ test_b(FieldOperand(ecx, Map::kBitField2Offset), |
| 488 1 << Map::kHasFastElements); | 487 1 << Map::kHasFastElements); |
| 489 __ j(zero, &check_number_dictionary, not_taken); | 488 __ j(zero, &check_number_dictionary, Label::kFar, not_taken); |
| 490 | 489 |
| 491 GenerateFastArrayLoad(masm, | 490 GenerateFastArrayLoad(masm, |
| 492 edx, | 491 edx, |
| 493 eax, | 492 eax, |
| 494 ecx, | 493 ecx, |
| 495 eax, | 494 eax, |
| 496 NULL, | 495 NULL, |
| 497 &slow); | 496 &slow); |
| 498 Isolate* isolate = masm->isolate(); | 497 Isolate* isolate = masm->isolate(); |
| 499 Counters* counters = isolate->counters(); | 498 Counters* counters = isolate->counters(); |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { | 656 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { |
| 658 // ----------- S t a t e ------------- | 657 // ----------- S t a t e ------------- |
| 659 // -- eax : key | 658 // -- eax : key |
| 660 // -- edx : receiver | 659 // -- edx : receiver |
| 661 // -- esp[0] : return address | 660 // -- esp[0] : return address |
| 662 // ----------------------------------- | 661 // ----------------------------------- |
| 663 Label slow; | 662 Label slow; |
| 664 | 663 |
| 665 // Check that the receiver isn't a smi. | 664 // Check that the receiver isn't a smi. |
| 666 __ test(edx, Immediate(kSmiTagMask)); | 665 __ test(edx, Immediate(kSmiTagMask)); |
| 667 __ j(zero, &slow, not_taken); | 666 __ j(zero, &slow, Label::kFar, not_taken); |
| 668 | 667 |
| 669 // Check that the key is an array index, that is Uint32. | 668 // Check that the key is an array index, that is Uint32. |
| 670 __ test(eax, Immediate(kSmiTagMask | kSmiSignMask)); | 669 __ test(eax, Immediate(kSmiTagMask | kSmiSignMask)); |
| 671 __ j(not_zero, &slow, not_taken); | 670 __ j(not_zero, &slow, Label::kFar, not_taken); |
| 672 | 671 |
| 673 // Get the map of the receiver. | 672 // Get the map of the receiver. |
| 674 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 673 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
| 675 | 674 |
| 676 // Check that it has indexed interceptor and access checks | 675 // Check that it has indexed interceptor and access checks |
| 677 // are not enabled for this object. | 676 // are not enabled for this object. |
| 678 __ movzx_b(ecx, FieldOperand(ecx, Map::kBitFieldOffset)); | 677 __ movzx_b(ecx, FieldOperand(ecx, Map::kBitFieldOffset)); |
| 679 __ and_(Operand(ecx), Immediate(kSlowCaseBitFieldMask)); | 678 __ and_(Operand(ecx), Immediate(kSlowCaseBitFieldMask)); |
| 680 __ cmp(Operand(ecx), Immediate(1 << Map::kHasIndexedInterceptor)); | 679 __ cmp(Operand(ecx), Immediate(1 << Map::kHasIndexedInterceptor)); |
| 681 __ j(not_zero, &slow, not_taken); | 680 __ j(not_zero, &slow, Label::kFar, not_taken); |
| 682 | 681 |
| 683 // Everything is fine, call runtime. | 682 // Everything is fine, call runtime. |
| 684 __ pop(ecx); | 683 __ pop(ecx); |
| 685 __ push(edx); // receiver | 684 __ push(edx); // receiver |
| 686 __ push(eax); // key | 685 __ push(eax); // key |
| 687 __ push(ecx); // return address | 686 __ push(ecx); // return address |
| 688 | 687 |
| 689 // Perform tail call to the entry. | 688 // Perform tail call to the entry. |
| 690 ExternalReference ref = | 689 ExternalReference ref = |
| 691 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor), | 690 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor), |
| (...skipping 10 matching lines...) Expand all Loading... |
| 702 // ----------- S t a t e ------------- | 701 // ----------- S t a t e ------------- |
| 703 // -- eax : value | 702 // -- eax : value |
| 704 // -- ecx : key | 703 // -- ecx : key |
| 705 // -- edx : receiver | 704 // -- edx : receiver |
| 706 // -- esp[0] : return address | 705 // -- esp[0] : return address |
| 707 // ----------------------------------- | 706 // ----------------------------------- |
| 708 Label slow, fast, array, extra; | 707 Label slow, fast, array, extra; |
| 709 | 708 |
| 710 // Check that the object isn't a smi. | 709 // Check that the object isn't a smi. |
| 711 __ test(edx, Immediate(kSmiTagMask)); | 710 __ test(edx, Immediate(kSmiTagMask)); |
| 712 __ j(zero, &slow, not_taken); | 711 __ j(zero, &slow, Label::kFar, not_taken); |
| 713 // Get the map from the receiver. | 712 // Get the map from the receiver. |
| 714 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); | 713 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); |
| 715 // Check that the receiver does not require access checks. We need | 714 // Check that the receiver does not require access checks. We need |
| 716 // to do this because this generic stub does not perform map checks. | 715 // to do this because this generic stub does not perform map checks. |
| 717 __ test_b(FieldOperand(edi, Map::kBitFieldOffset), | 716 __ test_b(FieldOperand(edi, Map::kBitFieldOffset), |
| 718 1 << Map::kIsAccessCheckNeeded); | 717 1 << Map::kIsAccessCheckNeeded); |
| 719 __ j(not_zero, &slow, not_taken); | 718 __ j(not_zero, &slow, Label::kFar, not_taken); |
| 720 // Check that the key is a smi. | 719 // Check that the key is a smi. |
| 721 __ test(ecx, Immediate(kSmiTagMask)); | 720 __ test(ecx, Immediate(kSmiTagMask)); |
| 722 __ j(not_zero, &slow, not_taken); | 721 __ j(not_zero, &slow, Label::kFar, not_taken); |
| 723 __ CmpInstanceType(edi, JS_ARRAY_TYPE); | 722 __ CmpInstanceType(edi, JS_ARRAY_TYPE); |
| 724 __ j(equal, &array); | 723 __ j(equal, &array); |
| 725 // Check that the object is some kind of JS object. | 724 // Check that the object is some kind of JS object. |
| 726 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); | 725 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); |
| 727 __ j(below, &slow, not_taken); | 726 __ j(below, &slow, Label::kFar, not_taken); |
| 728 | 727 |
| 729 // Object case: Check key against length in the elements array. | 728 // Object case: Check key against length in the elements array. |
| 730 // eax: value | 729 // eax: value |
| 731 // edx: JSObject | 730 // edx: JSObject |
| 732 // ecx: key (a smi) | 731 // ecx: key (a smi) |
| 733 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 732 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
| 734 // Check that the object is in fast mode and writable. | 733 // Check that the object is in fast mode and writable. |
| 735 __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, true); | 734 __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, true); |
| 736 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); | 735 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); |
| 737 __ j(below, &fast, taken); | 736 __ j(below, &fast, Label::kFar, taken); |
| 738 | 737 |
| 739 // Slow case: call runtime. | 738 // Slow case: call runtime. |
| 740 __ bind(&slow); | 739 __ bind(&slow); |
| 741 GenerateRuntimeSetProperty(masm, strict_mode); | 740 GenerateRuntimeSetProperty(masm, strict_mode); |
| 742 | 741 |
| 743 // Extra capacity case: Check if there is extra capacity to | 742 // Extra capacity case: Check if there is extra capacity to |
| 744 // perform the store and update the length. Used for adding one | 743 // perform the store and update the length. Used for adding one |
| 745 // element to the array by writing to array[array.length]. | 744 // element to the array by writing to array[array.length]. |
| 746 __ bind(&extra); | 745 __ bind(&extra); |
| 747 // eax: value | 746 // eax: value |
| 748 // edx: receiver, a JSArray | 747 // edx: receiver, a JSArray |
| 749 // ecx: key, a smi. | 748 // ecx: key, a smi. |
| 750 // edi: receiver->elements, a FixedArray | 749 // edi: receiver->elements, a FixedArray |
| 751 // flags: compare (ecx, edx.length()) | 750 // flags: compare (ecx, edx.length()) |
| 752 __ j(not_equal, &slow, not_taken); // do not leave holes in the array | 751 // do not leave holes in the array: |
| 752 __ j(not_equal, &slow, Label::kFar, not_taken); |
| 753 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); | 753 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); |
| 754 __ j(above_equal, &slow, not_taken); | 754 __ j(above_equal, &slow, Label::kFar, not_taken); |
| 755 // Add 1 to receiver->length, and go to fast array write. | 755 // Add 1 to receiver->length, and go to fast array write. |
| 756 __ add(FieldOperand(edx, JSArray::kLengthOffset), | 756 __ add(FieldOperand(edx, JSArray::kLengthOffset), |
| 757 Immediate(Smi::FromInt(1))); | 757 Immediate(Smi::FromInt(1))); |
| 758 __ jmp(&fast); | 758 __ jmp(&fast); |
| 759 | 759 |
| 760 // Array case: Get the length and the elements array from the JS | 760 // Array case: Get the length and the elements array from the JS |
| 761 // array. Check that the array is in fast mode (and writable); if it | 761 // array. Check that the array is in fast mode (and writable); if it |
| 762 // is the length is always a smi. | 762 // is the length is always a smi. |
| 763 __ bind(&array); | 763 __ bind(&array); |
| 764 // eax: value | 764 // eax: value |
| 765 // edx: receiver, a JSArray | 765 // edx: receiver, a JSArray |
| 766 // ecx: key, a smi. | 766 // ecx: key, a smi. |
| 767 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 767 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
| 768 __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, true); | 768 __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, true); |
| 769 | 769 |
| 770 // Check the key against the length in the array, compute the | 770 // Check the key against the length in the array, compute the |
| 771 // address to store into and fall through to fast case. | 771 // address to store into and fall through to fast case. |
| 772 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. | 772 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. |
| 773 __ j(above_equal, &extra, not_taken); | 773 __ j(above_equal, &extra, Label::kFar, not_taken); |
| 774 | 774 |
| 775 // Fast case: Do the store. | 775 // Fast case: Do the store. |
| 776 __ bind(&fast); | 776 __ bind(&fast); |
| 777 // eax: value | 777 // eax: value |
| 778 // ecx: key (a smi) | 778 // ecx: key (a smi) |
| 779 // edx: receiver | 779 // edx: receiver |
| 780 // edi: FixedArray receiver->elements | 780 // edi: FixedArray receiver->elements |
| 781 __ mov(CodeGenerator::FixedArrayElementOperand(edi, ecx), eax); | 781 __ mov(CodeGenerator::FixedArrayElementOperand(edi, ecx), eax); |
| 782 // Update write barrier for the elements array address. | 782 // Update write barrier for the elements array address. |
| 783 __ mov(edx, Operand(eax)); | 783 __ mov(edx, Operand(eax)); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 807 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx, | 807 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx, |
| 808 eax); | 808 eax); |
| 809 | 809 |
| 810 // If the stub cache probing failed, the receiver might be a value. | 810 // If the stub cache probing failed, the receiver might be a value. |
| 811 // For value objects, we use the map of the prototype objects for | 811 // For value objects, we use the map of the prototype objects for |
| 812 // the corresponding JSValue for the cache and that is what we need | 812 // the corresponding JSValue for the cache and that is what we need |
| 813 // to probe. | 813 // to probe. |
| 814 // | 814 // |
| 815 // Check for number. | 815 // Check for number. |
| 816 __ test(edx, Immediate(kSmiTagMask)); | 816 __ test(edx, Immediate(kSmiTagMask)); |
| 817 __ j(zero, &number, not_taken); | 817 __ j(zero, &number, Label::kFar, not_taken); |
| 818 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx); | 818 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx); |
| 819 __ j(not_equal, &non_number, taken); | 819 __ j(not_equal, &non_number, Label::kFar, taken); |
| 820 __ bind(&number); | 820 __ bind(&number); |
| 821 StubCompiler::GenerateLoadGlobalFunctionPrototype( | 821 StubCompiler::GenerateLoadGlobalFunctionPrototype( |
| 822 masm, Context::NUMBER_FUNCTION_INDEX, edx); | 822 masm, Context::NUMBER_FUNCTION_INDEX, edx); |
| 823 __ jmp(&probe); | 823 __ jmp(&probe); |
| 824 | 824 |
| 825 // Check for string. | 825 // Check for string. |
| 826 __ bind(&non_number); | 826 __ bind(&non_number); |
| 827 __ CmpInstanceType(ebx, FIRST_NONSTRING_TYPE); | 827 __ CmpInstanceType(ebx, FIRST_NONSTRING_TYPE); |
| 828 __ j(above_equal, &non_string, taken); | 828 __ j(above_equal, &non_string, Label::kFar, taken); |
| 829 StubCompiler::GenerateLoadGlobalFunctionPrototype( | 829 StubCompiler::GenerateLoadGlobalFunctionPrototype( |
| 830 masm, Context::STRING_FUNCTION_INDEX, edx); | 830 masm, Context::STRING_FUNCTION_INDEX, edx); |
| 831 __ jmp(&probe); | 831 __ jmp(&probe); |
| 832 | 832 |
| 833 // Check for boolean. | 833 // Check for boolean. |
| 834 __ bind(&non_string); | 834 __ bind(&non_string); |
| 835 __ cmp(edx, FACTORY->true_value()); | 835 __ cmp(edx, FACTORY->true_value()); |
| 836 __ j(equal, &boolean, not_taken); | 836 __ j(equal, &boolean, Label::kFar, not_taken); |
| 837 __ cmp(edx, FACTORY->false_value()); | 837 __ cmp(edx, FACTORY->false_value()); |
| 838 __ j(not_equal, &miss, taken); | 838 __ j(not_equal, &miss, Label::kFar, taken); |
| 839 __ bind(&boolean); | 839 __ bind(&boolean); |
| 840 StubCompiler::GenerateLoadGlobalFunctionPrototype( | 840 StubCompiler::GenerateLoadGlobalFunctionPrototype( |
| 841 masm, Context::BOOLEAN_FUNCTION_INDEX, edx); | 841 masm, Context::BOOLEAN_FUNCTION_INDEX, edx); |
| 842 | 842 |
| 843 // Probe the stub cache for the value object. | 843 // Probe the stub cache for the value object. |
| 844 __ bind(&probe); | 844 __ bind(&probe); |
| 845 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx, | 845 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx, |
| 846 no_reg); | 846 no_reg); |
| 847 __ bind(&miss); | 847 __ bind(&miss); |
| 848 } | 848 } |
| 849 | 849 |
| 850 | 850 |
| 851 static void GenerateFunctionTailCall(MacroAssembler* masm, | 851 static void GenerateFunctionTailCall(MacroAssembler* masm, |
| 852 int argc, | 852 int argc, |
| 853 Label* miss) { | 853 Label* miss) { |
| 854 // ----------- S t a t e ------------- | 854 // ----------- S t a t e ------------- |
| 855 // -- ecx : name | 855 // -- ecx : name |
| 856 // -- edi : function | 856 // -- edi : function |
| 857 // -- esp[0] : return address | 857 // -- esp[0] : return address |
| 858 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 858 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 859 // -- ... | 859 // -- ... |
| 860 // -- esp[(argc + 1) * 4] : receiver | 860 // -- esp[(argc + 1) * 4] : receiver |
| 861 // ----------------------------------- | 861 // ----------------------------------- |
| 862 | 862 |
| 863 // Check that the result is not a smi. | 863 // Check that the result is not a smi. |
| 864 __ test(edi, Immediate(kSmiTagMask)); | 864 __ test(edi, Immediate(kSmiTagMask)); |
| 865 __ j(zero, miss, not_taken); | 865 __ j(zero, miss, Label::kFar, not_taken); |
| 866 | 866 |
| 867 // Check that the value is a JavaScript function, fetching its map into eax. | 867 // Check that the value is a JavaScript function, fetching its map into eax. |
| 868 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); | 868 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); |
| 869 __ j(not_equal, miss, not_taken); | 869 __ j(not_equal, miss, Label::kFar, not_taken); |
| 870 | 870 |
| 871 // Invoke the function. | 871 // Invoke the function. |
| 872 ParameterCount actual(argc); | 872 ParameterCount actual(argc); |
| 873 __ InvokeFunction(edi, actual, JUMP_FUNCTION); | 873 __ InvokeFunction(edi, actual, JUMP_FUNCTION); |
| 874 } | 874 } |
| 875 | 875 |
| 876 // The generated code falls through if the call should be handled by runtime. | 876 // The generated code falls through if the call should be handled by runtime. |
| 877 static void GenerateCallNormal(MacroAssembler* masm, int argc) { | 877 static void GenerateCallNormal(MacroAssembler* masm, int argc) { |
| 878 // ----------- S t a t e ------------- | 878 // ----------- S t a t e ------------- |
| 879 // -- ecx : name | 879 // -- ecx : name |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 935 // Move result to edi and exit the internal frame. | 935 // Move result to edi and exit the internal frame. |
| 936 __ mov(edi, eax); | 936 __ mov(edi, eax); |
| 937 __ LeaveInternalFrame(); | 937 __ LeaveInternalFrame(); |
| 938 | 938 |
| 939 // Check if the receiver is a global object of some sort. | 939 // Check if the receiver is a global object of some sort. |
| 940 // This can happen only for regular CallIC but not KeyedCallIC. | 940 // This can happen only for regular CallIC but not KeyedCallIC. |
| 941 if (id == IC::kCallIC_Miss) { | 941 if (id == IC::kCallIC_Miss) { |
| 942 Label invoke, global; | 942 Label invoke, global; |
| 943 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); // receiver | 943 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); // receiver |
| 944 __ test(edx, Immediate(kSmiTagMask)); | 944 __ test(edx, Immediate(kSmiTagMask)); |
| 945 __ j(zero, &invoke, not_taken); | 945 __ j(zero, &invoke, Label::kNear, not_taken); |
| 946 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); | 946 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); |
| 947 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 947 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
| 948 __ cmp(ebx, JS_GLOBAL_OBJECT_TYPE); | 948 __ cmp(ebx, JS_GLOBAL_OBJECT_TYPE); |
| 949 __ j(equal, &global); | 949 __ j(equal, &global, Label::kNear); |
| 950 __ cmp(ebx, JS_BUILTINS_OBJECT_TYPE); | 950 __ cmp(ebx, JS_BUILTINS_OBJECT_TYPE); |
| 951 __ j(not_equal, &invoke); | 951 __ j(not_equal, &invoke, Label::kNear); |
| 952 | 952 |
| 953 // Patch the receiver on the stack. | 953 // Patch the receiver on the stack. |
| 954 __ bind(&global); | 954 __ bind(&global); |
| 955 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 955 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
| 956 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 956 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
| 957 __ bind(&invoke); | 957 __ bind(&invoke); |
| 958 } | 958 } |
| 959 | 959 |
| 960 // Invoke the function. | 960 // Invoke the function. |
| 961 ParameterCount actual(argc); | 961 ParameterCount actual(argc); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1017 | 1017 |
| 1018 // Get the receiver of the function from the stack; 1 ~ return address. | 1018 // Get the receiver of the function from the stack; 1 ~ return address. |
| 1019 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1019 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1020 | 1020 |
| 1021 Label do_call, slow_call, slow_load, slow_reload_receiver; | 1021 Label do_call, slow_call, slow_load, slow_reload_receiver; |
| 1022 Label check_number_dictionary, check_string, lookup_monomorphic_cache; | 1022 Label check_number_dictionary, check_string, lookup_monomorphic_cache; |
| 1023 Label index_smi, index_string; | 1023 Label index_smi, index_string; |
| 1024 | 1024 |
| 1025 // Check that the key is a smi. | 1025 // Check that the key is a smi. |
| 1026 __ test(ecx, Immediate(kSmiTagMask)); | 1026 __ test(ecx, Immediate(kSmiTagMask)); |
| 1027 __ j(not_zero, &check_string, not_taken); | 1027 __ j(not_zero, &check_string, Label::kFar, not_taken); |
| 1028 | 1028 |
| 1029 __ bind(&index_smi); | 1029 __ bind(&index_smi); |
| 1030 // Now the key is known to be a smi. This place is also jumped to from | 1030 // Now the key is known to be a smi. This place is also jumped to from |
| 1031 // where a numeric string is converted to a smi. | 1031 // where a numeric string is converted to a smi. |
| 1032 | 1032 |
| 1033 GenerateKeyedLoadReceiverCheck( | 1033 GenerateKeyedLoadReceiverCheck( |
| 1034 masm, edx, eax, Map::kHasIndexedInterceptor, &slow_call); | 1034 masm, edx, eax, Map::kHasIndexedInterceptor, &slow_call); |
| 1035 | 1035 |
| 1036 GenerateFastArrayLoad( | 1036 GenerateFastArrayLoad( |
| 1037 masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load); | 1037 masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load); |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1307 // Value must be a number, but only smis are accepted as the most common case. | 1307 // Value must be a number, but only smis are accepted as the most common case. |
| 1308 | 1308 |
| 1309 Label miss; | 1309 Label miss; |
| 1310 | 1310 |
| 1311 Register receiver = edx; | 1311 Register receiver = edx; |
| 1312 Register value = eax; | 1312 Register value = eax; |
| 1313 Register scratch = ebx; | 1313 Register scratch = ebx; |
| 1314 | 1314 |
| 1315 // Check that the receiver isn't a smi. | 1315 // Check that the receiver isn't a smi. |
| 1316 __ test(receiver, Immediate(kSmiTagMask)); | 1316 __ test(receiver, Immediate(kSmiTagMask)); |
| 1317 __ j(zero, &miss, not_taken); | 1317 __ j(zero, &miss, Label::kFar, not_taken); |
| 1318 | 1318 |
| 1319 // Check that the object is a JS array. | 1319 // Check that the object is a JS array. |
| 1320 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); | 1320 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); |
| 1321 __ j(not_equal, &miss, not_taken); | 1321 __ j(not_equal, &miss, Label::kFar, not_taken); |
| 1322 | 1322 |
| 1323 // Check that elements are FixedArray. | 1323 // Check that elements are FixedArray. |
| 1324 // We rely on StoreIC_ArrayLength below to deal with all types of | 1324 // We rely on StoreIC_ArrayLength below to deal with all types of |
| 1325 // fast elements (including COW). | 1325 // fast elements (including COW). |
| 1326 __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset)); | 1326 __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset)); |
| 1327 __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch); | 1327 __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch); |
| 1328 __ j(not_equal, &miss, not_taken); | 1328 __ j(not_equal, &miss, Label::kFar, not_taken); |
| 1329 | 1329 |
| 1330 // Check that value is a smi. | 1330 // Check that value is a smi. |
| 1331 __ test(value, Immediate(kSmiTagMask)); | 1331 __ test(value, Immediate(kSmiTagMask)); |
| 1332 __ j(not_zero, &miss, not_taken); | 1332 __ j(not_zero, &miss, Label::kFar, not_taken); |
| 1333 | 1333 |
| 1334 // Prepare tail call to StoreIC_ArrayLength. | 1334 // Prepare tail call to StoreIC_ArrayLength. |
| 1335 __ pop(scratch); | 1335 __ pop(scratch); |
| 1336 __ push(receiver); | 1336 __ push(receiver); |
| 1337 __ push(value); | 1337 __ push(value); |
| 1338 __ push(scratch); // return address | 1338 __ push(scratch); // return address |
| 1339 | 1339 |
| 1340 ExternalReference ref = | 1340 ExternalReference ref = |
| 1341 ExternalReference(IC_Utility(kStoreIC_ArrayLength), masm->isolate()); | 1341 ExternalReference(IC_Utility(kStoreIC_ArrayLength), masm->isolate()); |
| 1342 __ TailCallExternalReference(ref, 2, 1); | 1342 __ TailCallExternalReference(ref, 2, 1); |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1538 Condition cc = *jmp_address == Assembler::kJncShortOpcode | 1538 Condition cc = *jmp_address == Assembler::kJncShortOpcode |
| 1539 ? not_zero | 1539 ? not_zero |
| 1540 : zero; | 1540 : zero; |
| 1541 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1541 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
| 1542 } | 1542 } |
| 1543 | 1543 |
| 1544 | 1544 |
| 1545 } } // namespace v8::internal | 1545 } } // namespace v8::internal |
| 1546 | 1546 |
| 1547 #endif // V8_TARGET_ARCH_IA32 | 1547 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |