| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_X87 | 7 #if V8_TARGET_ARCH_X87 |
| 8 | 8 |
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/ic-inl.h" | 10 #include "src/ic-inl.h" |
| (...skipping 537 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 548 __ IncrementCounter(counters->keyed_load_generic_symbol(), 1); | 548 __ IncrementCounter(counters->keyed_load_generic_symbol(), 1); |
| 549 __ ret(0); | 549 __ ret(0); |
| 550 | 550 |
| 551 __ bind(&index_name); | 551 __ bind(&index_name); |
| 552 __ IndexFromHash(ebx, key); | 552 __ IndexFromHash(ebx, key); |
| 553 // Now jump to the place where smi keys are handled. | 553 // Now jump to the place where smi keys are handled. |
| 554 __ jmp(&index_smi); | 554 __ jmp(&index_smi); |
| 555 } | 555 } |
| 556 | 556 |
| 557 | 557 |
| 558 // A register that isn't one of the parameters to the load ic. | |
| 559 static const Register LoadIC_TempRegister() { return ebx; } | |
| 560 | |
| 561 | |
| 562 // A register that isn't one of the parameters to the load ic. | |
| 563 static const Register KeyedLoadIC_TempRegister() { | |
| 564 return LoadIC_TempRegister(); | |
| 565 } | |
| 566 | |
| 567 | |
| 568 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 558 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
| 569 // Return address is on the stack. | 559 // Return address is on the stack. |
| 570 Label miss; | 560 Label miss; |
| 571 | 561 |
| 572 Register receiver = ReceiverRegister(); | 562 Register receiver = ReceiverRegister(); |
| 573 Register index = NameRegister(); | 563 Register index = NameRegister(); |
| 574 Register scratch = KeyedLoadIC_TempRegister(); | 564 Register scratch = ebx; |
| 565 ASSERT(!scratch.is(receiver) && !scratch.is(index)); |
| 575 Register result = eax; | 566 Register result = eax; |
| 576 ASSERT(!result.is(scratch)); | 567 ASSERT(!result.is(scratch)); |
| 577 | 568 |
| 578 StringCharAtGenerator char_at_generator(receiver, | 569 StringCharAtGenerator char_at_generator(receiver, |
| 579 index, | 570 index, |
| 580 scratch, | 571 scratch, |
| 581 result, | 572 result, |
| 582 &miss, // When not a string. | 573 &miss, // When not a string. |
| 583 &miss, // When not a number. | 574 &miss, // When not a number. |
| 584 &miss, // When index out of range. | 575 &miss, // When index out of range. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 658 __ cmp(unmapped_location, factory->the_hole_value()); | 649 __ cmp(unmapped_location, factory->the_hole_value()); |
| 659 __ j(equal, &slow); | 650 __ j(equal, &slow); |
| 660 __ mov(eax, unmapped_location); | 651 __ mov(eax, unmapped_location); |
| 661 __ Ret(); | 652 __ Ret(); |
| 662 __ bind(&slow); | 653 __ bind(&slow); |
| 663 GenerateMiss(masm); | 654 GenerateMiss(masm); |
| 664 } | 655 } |
| 665 | 656 |
| 666 | 657 |
| 667 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { | 658 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { |
| 668 // ----------- S t a t e ------------- | 659 // Return address is on the stack. |
| 669 // -- eax : value | |
| 670 // -- ecx : key | |
| 671 // -- edx : receiver | |
| 672 // -- esp[0] : return address | |
| 673 // ----------------------------------- | |
| 674 Label slow, notin; | 660 Label slow, notin; |
| 661 Register receiver = ReceiverRegister(); |
| 662 Register name = NameRegister(); |
| 663 Register value = ValueRegister(); |
| 664 ASSERT(receiver.is(edx)); |
| 665 ASSERT(name.is(ecx)); |
| 666 ASSERT(value.is(eax)); |
| 667 |
| 675 Operand mapped_location = | 668 Operand mapped_location = |
| 676 GenerateMappedArgumentsLookup(masm, edx, ecx, ebx, edi, ¬in, &slow); | 669 GenerateMappedArgumentsLookup(masm, receiver, name, ebx, edi, ¬in, |
| 677 __ mov(mapped_location, eax); | 670 &slow); |
| 671 __ mov(mapped_location, value); |
| 678 __ lea(ecx, mapped_location); | 672 __ lea(ecx, mapped_location); |
| 679 __ mov(edx, eax); | 673 __ mov(edx, value); |
| 680 __ RecordWrite(ebx, ecx, edx); | 674 __ RecordWrite(ebx, ecx, edx); |
| 681 __ Ret(); | 675 __ Ret(); |
| 682 __ bind(¬in); | 676 __ bind(¬in); |
| 683 // The unmapped lookup expects that the parameter map is in ebx. | 677 // The unmapped lookup expects that the parameter map is in ebx. |
| 684 Operand unmapped_location = | 678 Operand unmapped_location = |
| 685 GenerateUnmappedArgumentsLookup(masm, ecx, ebx, edi, &slow); | 679 GenerateUnmappedArgumentsLookup(masm, name, ebx, edi, &slow); |
| 686 __ mov(unmapped_location, eax); | 680 __ mov(unmapped_location, value); |
| 687 __ lea(edi, unmapped_location); | 681 __ lea(edi, unmapped_location); |
| 688 __ mov(edx, eax); | 682 __ mov(edx, value); |
| 689 __ RecordWrite(ebx, edi, edx); | 683 __ RecordWrite(ebx, edi, edx); |
| 690 __ Ret(); | 684 __ Ret(); |
| 691 __ bind(&slow); | 685 __ bind(&slow); |
| 692 GenerateMiss(masm); | 686 GenerateMiss(masm); |
| 693 } | 687 } |
| 694 | 688 |
| 695 | 689 |
| 696 static void KeyedStoreGenerateGenericHelper( | 690 static void KeyedStoreGenerateGenericHelper( |
| 697 MacroAssembler* masm, | 691 MacroAssembler* masm, |
| 698 Label* fast_object, | 692 Label* fast_object, |
| 699 Label* fast_double, | 693 Label* fast_double, |
| 700 Label* slow, | 694 Label* slow, |
| 701 KeyedStoreCheckMap check_map, | 695 KeyedStoreCheckMap check_map, |
| 702 KeyedStoreIncrementLength increment_length) { | 696 KeyedStoreIncrementLength increment_length) { |
| 703 Label transition_smi_elements; | 697 Label transition_smi_elements; |
| 704 Label finish_object_store, non_double_value, transition_double_elements; | 698 Label finish_object_store, non_double_value, transition_double_elements; |
| 705 Label fast_double_without_map_check; | 699 Label fast_double_without_map_check; |
| 706 // eax: value | 700 Register receiver = KeyedStoreIC::ReceiverRegister(); |
| 707 // ecx: key (a smi) | 701 Register key = KeyedStoreIC::NameRegister(); |
| 708 // edx: receiver | 702 Register value = KeyedStoreIC::ValueRegister(); |
| 703 ASSERT(receiver.is(edx)); |
| 704 ASSERT(key.is(ecx)); |
| 705 ASSERT(value.is(eax)); |
| 706 // key is a smi. |
| 709 // ebx: FixedArray receiver->elements | 707 // ebx: FixedArray receiver->elements |
| 710 // edi: receiver map | 708 // edi: receiver map |
| 711 // Fast case: Do the store, could either Object or double. | 709 // Fast case: Do the store, could either Object or double. |
| 712 __ bind(fast_object); | 710 __ bind(fast_object); |
| 713 if (check_map == kCheckMap) { | 711 if (check_map == kCheckMap) { |
| 714 __ mov(edi, FieldOperand(ebx, HeapObject::kMapOffset)); | 712 __ mov(edi, FieldOperand(ebx, HeapObject::kMapOffset)); |
| 715 __ cmp(edi, masm->isolate()->factory()->fixed_array_map()); | 713 __ cmp(edi, masm->isolate()->factory()->fixed_array_map()); |
| 716 __ j(not_equal, fast_double); | 714 __ j(not_equal, fast_double); |
| 717 } | 715 } |
| 718 | 716 |
| 719 // HOLECHECK: guards "A[i] = V" | 717 // HOLECHECK: guards "A[i] = V" |
| 720 // We have to go to the runtime if the current value is the hole because | 718 // We have to go to the runtime if the current value is the hole because |
| 721 // there may be a callback on the element | 719 // there may be a callback on the element |
| 722 Label holecheck_passed1; | 720 Label holecheck_passed1; |
| 723 __ cmp(FixedArrayElementOperand(ebx, ecx), | 721 __ cmp(FixedArrayElementOperand(ebx, key), |
| 724 masm->isolate()->factory()->the_hole_value()); | 722 masm->isolate()->factory()->the_hole_value()); |
| 725 __ j(not_equal, &holecheck_passed1); | 723 __ j(not_equal, &holecheck_passed1); |
| 726 __ JumpIfDictionaryInPrototypeChain(edx, ebx, edi, slow); | 724 __ JumpIfDictionaryInPrototypeChain(receiver, ebx, edi, slow); |
| 727 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); | 725 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset)); |
| 728 | 726 |
| 729 __ bind(&holecheck_passed1); | 727 __ bind(&holecheck_passed1); |
| 730 | 728 |
| 731 // Smi stores don't require further checks. | 729 // Smi stores don't require further checks. |
| 732 Label non_smi_value; | 730 Label non_smi_value; |
| 733 __ JumpIfNotSmi(eax, &non_smi_value); | 731 __ JumpIfNotSmi(value, &non_smi_value); |
| 734 if (increment_length == kIncrementLength) { | 732 if (increment_length == kIncrementLength) { |
| 735 // Add 1 to receiver->length. | 733 // Add 1 to receiver->length. |
| 736 __ add(FieldOperand(edx, JSArray::kLengthOffset), | 734 __ add(FieldOperand(receiver, JSArray::kLengthOffset), |
| 737 Immediate(Smi::FromInt(1))); | 735 Immediate(Smi::FromInt(1))); |
| 738 } | 736 } |
| 739 // It's irrelevant whether array is smi-only or not when writing a smi. | 737 // It's irrelevant whether array is smi-only or not when writing a smi. |
| 740 __ mov(FixedArrayElementOperand(ebx, ecx), eax); | 738 __ mov(FixedArrayElementOperand(ebx, key), value); |
| 741 __ ret(0); | 739 __ ret(0); |
| 742 | 740 |
| 743 __ bind(&non_smi_value); | 741 __ bind(&non_smi_value); |
| 744 // Escape to elements kind transition case. | 742 // Escape to elements kind transition case. |
| 745 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); | 743 __ mov(edi, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 746 __ CheckFastObjectElements(edi, &transition_smi_elements); | 744 __ CheckFastObjectElements(edi, &transition_smi_elements); |
| 747 | 745 |
| 748 // Fast elements array, store the value to the elements backing store. | 746 // Fast elements array, store the value to the elements backing store. |
| 749 __ bind(&finish_object_store); | 747 __ bind(&finish_object_store); |
| 750 if (increment_length == kIncrementLength) { | 748 if (increment_length == kIncrementLength) { |
| 751 // Add 1 to receiver->length. | 749 // Add 1 to receiver->length. |
| 752 __ add(FieldOperand(edx, JSArray::kLengthOffset), | 750 __ add(FieldOperand(receiver, JSArray::kLengthOffset), |
| 753 Immediate(Smi::FromInt(1))); | 751 Immediate(Smi::FromInt(1))); |
| 754 } | 752 } |
| 755 __ mov(FixedArrayElementOperand(ebx, ecx), eax); | 753 __ mov(FixedArrayElementOperand(ebx, key), value); |
| 756 // Update write barrier for the elements array address. | 754 // Update write barrier for the elements array address. |
| 757 __ mov(edx, eax); // Preserve the value which is returned. | 755 __ mov(edx, value); // Preserve the value which is returned. |
| 758 __ RecordWriteArray( | 756 __ RecordWriteArray( |
| 759 ebx, edx, ecx, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | 757 ebx, edx, key, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
| 760 __ ret(0); | 758 __ ret(0); |
| 761 | 759 |
| 762 __ bind(fast_double); | 760 __ bind(fast_double); |
| 763 if (check_map == kCheckMap) { | 761 if (check_map == kCheckMap) { |
| 764 // Check for fast double array case. If this fails, call through to the | 762 // Check for fast double array case. If this fails, call through to the |
| 765 // runtime. | 763 // runtime. |
| 766 __ cmp(edi, masm->isolate()->factory()->fixed_double_array_map()); | 764 __ cmp(edi, masm->isolate()->factory()->fixed_double_array_map()); |
| 767 __ j(not_equal, slow); | 765 __ j(not_equal, slow); |
| 768 // If the value is a number, store it as a double in the FastDoubleElements | 766 // If the value is a number, store it as a double in the FastDoubleElements |
| 769 // array. | 767 // array. |
| 770 } | 768 } |
| 771 | 769 |
| 772 // HOLECHECK: guards "A[i] double hole?" | 770 // HOLECHECK: guards "A[i] double hole?" |
| 773 // We have to see if the double version of the hole is present. If so | 771 // We have to see if the double version of the hole is present. If so |
| 774 // go to the runtime. | 772 // go to the runtime. |
| 775 uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); | 773 uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); |
| 776 __ cmp(FieldOperand(ebx, ecx, times_4, offset), Immediate(kHoleNanUpper32)); | 774 __ cmp(FieldOperand(ebx, key, times_4, offset), Immediate(kHoleNanUpper32)); |
| 777 __ j(not_equal, &fast_double_without_map_check); | 775 __ j(not_equal, &fast_double_without_map_check); |
| 778 __ JumpIfDictionaryInPrototypeChain(edx, ebx, edi, slow); | 776 __ JumpIfDictionaryInPrototypeChain(receiver, ebx, edi, slow); |
| 779 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); | 777 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset)); |
| 780 | 778 |
| 781 __ bind(&fast_double_without_map_check); | 779 __ bind(&fast_double_without_map_check); |
| 782 __ StoreNumberToDoubleElements(eax, ebx, ecx, edi, | 780 __ StoreNumberToDoubleElements(value, ebx, key, edi, |
| 783 &transition_double_elements, false); | 781 &transition_double_elements, false); |
| 784 if (increment_length == kIncrementLength) { | 782 if (increment_length == kIncrementLength) { |
| 785 // Add 1 to receiver->length. | 783 // Add 1 to receiver->length. |
| 786 __ add(FieldOperand(edx, JSArray::kLengthOffset), | 784 __ add(FieldOperand(receiver, JSArray::kLengthOffset), |
| 787 Immediate(Smi::FromInt(1))); | 785 Immediate(Smi::FromInt(1))); |
| 788 } | 786 } |
| 789 __ ret(0); | 787 __ ret(0); |
| 790 | 788 |
| 791 __ bind(&transition_smi_elements); | 789 __ bind(&transition_smi_elements); |
| 792 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); | 790 __ mov(ebx, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 793 | 791 |
| 794 // Transition the array appropriately depending on the value type. | 792 // Transition the array appropriately depending on the value type. |
| 795 __ CheckMap(eax, | 793 __ CheckMap(value, |
| 796 masm->isolate()->factory()->heap_number_map(), | 794 masm->isolate()->factory()->heap_number_map(), |
| 797 &non_double_value, | 795 &non_double_value, |
| 798 DONT_DO_SMI_CHECK); | 796 DONT_DO_SMI_CHECK); |
| 799 | 797 |
| 800 // Value is a double. Transition FAST_SMI_ELEMENTS -> FAST_DOUBLE_ELEMENTS | 798 // Value is a double. Transition FAST_SMI_ELEMENTS -> FAST_DOUBLE_ELEMENTS |
| 801 // and complete the store. | 799 // and complete the store. |
| 802 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, | 800 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, |
| 803 FAST_DOUBLE_ELEMENTS, | 801 FAST_DOUBLE_ELEMENTS, |
| 804 ebx, | 802 ebx, |
| 805 edi, | 803 edi, |
| 806 slow); | 804 slow); |
| 807 AllocationSiteMode mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, | 805 AllocationSiteMode mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, |
| 808 FAST_DOUBLE_ELEMENTS); | 806 FAST_DOUBLE_ELEMENTS); |
| 809 ElementsTransitionGenerator::GenerateSmiToDouble(masm, mode, slow); | 807 ElementsTransitionGenerator::GenerateSmiToDouble(masm, mode, slow); |
| 810 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); | 808 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset)); |
| 811 __ jmp(&fast_double_without_map_check); | 809 __ jmp(&fast_double_without_map_check); |
| 812 | 810 |
| 813 __ bind(&non_double_value); | 811 __ bind(&non_double_value); |
| 814 // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS | 812 // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS |
| 815 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, | 813 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, |
| 816 FAST_ELEMENTS, | 814 FAST_ELEMENTS, |
| 817 ebx, | 815 ebx, |
| 818 edi, | 816 edi, |
| 819 slow); | 817 slow); |
| 820 mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS); | 818 mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS); |
| 821 ElementsTransitionGenerator::GenerateMapChangeElementsTransition(masm, mode, | 819 ElementsTransitionGenerator::GenerateMapChangeElementsTransition(masm, mode, |
| 822 slow); | 820 slow); |
| 823 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); | 821 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset)); |
| 824 __ jmp(&finish_object_store); | 822 __ jmp(&finish_object_store); |
| 825 | 823 |
| 826 __ bind(&transition_double_elements); | 824 __ bind(&transition_double_elements); |
| 827 // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a | 825 // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a |
| 828 // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and | 826 // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and |
| 829 // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS | 827 // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS |
| 830 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); | 828 __ mov(ebx, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 831 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, | 829 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, |
| 832 FAST_ELEMENTS, | 830 FAST_ELEMENTS, |
| 833 ebx, | 831 ebx, |
| 834 edi, | 832 edi, |
| 835 slow); | 833 slow); |
| 836 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS); | 834 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS); |
| 837 ElementsTransitionGenerator::GenerateDoubleToObject(masm, mode, slow); | 835 ElementsTransitionGenerator::GenerateDoubleToObject(masm, mode, slow); |
| 838 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); | 836 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset)); |
| 839 __ jmp(&finish_object_store); | 837 __ jmp(&finish_object_store); |
| 840 } | 838 } |
| 841 | 839 |
| 842 | 840 |
| 843 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, | 841 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, |
| 844 StrictMode strict_mode) { | 842 StrictMode strict_mode) { |
| 845 // ----------- S t a t e ------------- | 843 // Return address is on the stack. |
| 846 // -- eax : value | |
| 847 // -- ecx : key | |
| 848 // -- edx : receiver | |
| 849 // -- esp[0] : return address | |
| 850 // ----------------------------------- | |
| 851 Label slow, fast_object, fast_object_grow; | 844 Label slow, fast_object, fast_object_grow; |
| 852 Label fast_double, fast_double_grow; | 845 Label fast_double, fast_double_grow; |
| 853 Label array, extra, check_if_double_array; | 846 Label array, extra, check_if_double_array; |
| 847 Register receiver = ReceiverRegister(); |
| 848 Register key = NameRegister(); |
| 849 ASSERT(receiver.is(edx)); |
| 850 ASSERT(key.is(ecx)); |
| 854 | 851 |
| 855 // Check that the object isn't a smi. | 852 // Check that the object isn't a smi. |
| 856 __ JumpIfSmi(edx, &slow); | 853 __ JumpIfSmi(receiver, &slow); |
| 857 // Get the map from the receiver. | 854 // Get the map from the receiver. |
| 858 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); | 855 __ mov(edi, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 859 // Check that the receiver does not require access checks and is not observed. | 856 // Check that the receiver does not require access checks and is not observed. |
| 860 // The generic stub does not perform map checks or handle observed objects. | 857 // The generic stub does not perform map checks or handle observed objects. |
| 861 __ test_b(FieldOperand(edi, Map::kBitFieldOffset), | 858 __ test_b(FieldOperand(edi, Map::kBitFieldOffset), |
| 862 1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved); | 859 1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved); |
| 863 __ j(not_zero, &slow); | 860 __ j(not_zero, &slow); |
| 864 // Check that the key is a smi. | 861 // Check that the key is a smi. |
| 865 __ JumpIfNotSmi(ecx, &slow); | 862 __ JumpIfNotSmi(key, &slow); |
| 866 __ CmpInstanceType(edi, JS_ARRAY_TYPE); | 863 __ CmpInstanceType(edi, JS_ARRAY_TYPE); |
| 867 __ j(equal, &array); | 864 __ j(equal, &array); |
| 868 // Check that the object is some kind of JSObject. | 865 // Check that the object is some kind of JSObject. |
| 869 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); | 866 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); |
| 870 __ j(below, &slow); | 867 __ j(below, &slow); |
| 871 | 868 |
| 872 // Object case: Check key against length in the elements array. | 869 // Object case: Check key against length in the elements array. |
| 873 // eax: value | 870 // Key is a smi. |
| 874 // edx: JSObject | |
| 875 // ecx: key (a smi) | |
| 876 // edi: receiver map | 871 // edi: receiver map |
| 877 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); | 872 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset)); |
| 878 // Check array bounds. Both the key and the length of FixedArray are smis. | 873 // Check array bounds. Both the key and the length of FixedArray are smis. |
| 879 __ cmp(ecx, FieldOperand(ebx, FixedArray::kLengthOffset)); | 874 __ cmp(key, FieldOperand(ebx, FixedArray::kLengthOffset)); |
| 880 __ j(below, &fast_object); | 875 __ j(below, &fast_object); |
| 881 | 876 |
| 882 // Slow case: call runtime. | 877 // Slow case: call runtime. |
| 883 __ bind(&slow); | 878 __ bind(&slow); |
| 884 GenerateRuntimeSetProperty(masm, strict_mode); | 879 GenerateRuntimeSetProperty(masm, strict_mode); |
| 885 | 880 |
| 886 // Extra capacity case: Check if there is extra capacity to | 881 // Extra capacity case: Check if there is extra capacity to |
| 887 // perform the store and update the length. Used for adding one | 882 // perform the store and update the length. Used for adding one |
| 888 // element to the array by writing to array[array.length]. | 883 // element to the array by writing to array[array.length]. |
| 889 __ bind(&extra); | 884 __ bind(&extra); |
| 890 // eax: value | 885 // receiver is a JSArray. |
| 891 // edx: receiver, a JSArray | 886 // key is a smi. |
| 892 // ecx: key, a smi. | |
| 893 // ebx: receiver->elements, a FixedArray | 887 // ebx: receiver->elements, a FixedArray |
| 894 // edi: receiver map | 888 // edi: receiver map |
| 895 // flags: compare (ecx, edx.length()) | 889 // flags: compare (key, receiver.length()) |
| 896 // do not leave holes in the array: | 890 // do not leave holes in the array: |
| 897 __ j(not_equal, &slow); | 891 __ j(not_equal, &slow); |
| 898 __ cmp(ecx, FieldOperand(ebx, FixedArray::kLengthOffset)); | 892 __ cmp(key, FieldOperand(ebx, FixedArray::kLengthOffset)); |
| 899 __ j(above_equal, &slow); | 893 __ j(above_equal, &slow); |
| 900 __ mov(edi, FieldOperand(ebx, HeapObject::kMapOffset)); | 894 __ mov(edi, FieldOperand(ebx, HeapObject::kMapOffset)); |
| 901 __ cmp(edi, masm->isolate()->factory()->fixed_array_map()); | 895 __ cmp(edi, masm->isolate()->factory()->fixed_array_map()); |
| 902 __ j(not_equal, &check_if_double_array); | 896 __ j(not_equal, &check_if_double_array); |
| 903 __ jmp(&fast_object_grow); | 897 __ jmp(&fast_object_grow); |
| 904 | 898 |
| 905 __ bind(&check_if_double_array); | 899 __ bind(&check_if_double_array); |
| 906 __ cmp(edi, masm->isolate()->factory()->fixed_double_array_map()); | 900 __ cmp(edi, masm->isolate()->factory()->fixed_double_array_map()); |
| 907 __ j(not_equal, &slow); | 901 __ j(not_equal, &slow); |
| 908 __ jmp(&fast_double_grow); | 902 __ jmp(&fast_double_grow); |
| 909 | 903 |
| 910 // Array case: Get the length and the elements array from the JS | 904 // Array case: Get the length and the elements array from the JS |
| 911 // array. Check that the array is in fast mode (and writable); if it | 905 // array. Check that the array is in fast mode (and writable); if it |
| 912 // is the length is always a smi. | 906 // is the length is always a smi. |
| 913 __ bind(&array); | 907 __ bind(&array); |
| 914 // eax: value | 908 // receiver is a JSArray. |
| 915 // edx: receiver, a JSArray | 909 // key is a smi. |
| 916 // ecx: key, a smi. | |
| 917 // edi: receiver map | 910 // edi: receiver map |
| 918 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); | 911 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset)); |
| 919 | 912 |
| 920 // Check the key against the length in the array and fall through to the | 913 // Check the key against the length in the array and fall through to the |
| 921 // common store code. | 914 // common store code. |
| 922 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. | 915 __ cmp(key, FieldOperand(receiver, JSArray::kLengthOffset)); // Compare smis. |
| 923 __ j(above_equal, &extra); | 916 __ j(above_equal, &extra); |
| 924 | 917 |
| 925 KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double, | 918 KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double, |
| 926 &slow, kCheckMap, kDontIncrementLength); | 919 &slow, kCheckMap, kDontIncrementLength); |
| 927 KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow, | 920 KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow, |
| 928 &slow, kDontCheckMap, kIncrementLength); | 921 &slow, kDontCheckMap, kIncrementLength); |
| 929 } | 922 } |
| 930 | 923 |
| 931 | 924 |
| 932 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { | 925 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 967 // Dictionary load failed, go slow (but don't miss). | 960 // Dictionary load failed, go slow (but don't miss). |
| 968 __ bind(&slow); | 961 __ bind(&slow); |
| 969 GenerateRuntimeGetProperty(masm); | 962 GenerateRuntimeGetProperty(masm); |
| 970 | 963 |
| 971 // Cache miss: Jump to runtime. | 964 // Cache miss: Jump to runtime. |
| 972 __ bind(&miss); | 965 __ bind(&miss); |
| 973 GenerateMiss(masm); | 966 GenerateMiss(masm); |
| 974 } | 967 } |
| 975 | 968 |
| 976 | 969 |
| 970 static void LoadIC_PushArgs(MacroAssembler* masm) { |
| 971 Register receiver = LoadIC::ReceiverRegister(); |
| 972 Register name = LoadIC::NameRegister(); |
| 973 ASSERT(!ebx.is(receiver) && !ebx.is(name)); |
| 974 |
| 975 __ pop(ebx); |
| 976 __ push(receiver); |
| 977 __ push(name); |
| 978 __ push(ebx); |
| 979 } |
| 980 |
| 981 |
| 977 void LoadIC::GenerateMiss(MacroAssembler* masm) { | 982 void LoadIC::GenerateMiss(MacroAssembler* masm) { |
| 978 // Return address is on the stack. | 983 // Return address is on the stack. |
| 979 __ IncrementCounter(masm->isolate()->counters()->load_miss(), 1); | 984 __ IncrementCounter(masm->isolate()->counters()->load_miss(), 1); |
| 980 | 985 |
| 981 __ pop(LoadIC_TempRegister()); | 986 LoadIC_PushArgs(masm); |
| 982 __ push(ReceiverRegister()); // receiver | |
| 983 __ push(NameRegister()); // name | |
| 984 __ push(LoadIC_TempRegister()); // return address | |
| 985 | 987 |
| 986 // Perform tail call to the entry. | 988 // Perform tail call to the entry. |
| 987 ExternalReference ref = | 989 ExternalReference ref = |
| 988 ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate()); | 990 ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate()); |
| 989 __ TailCallExternalReference(ref, 2, 1); | 991 __ TailCallExternalReference(ref, 2, 1); |
| 990 } | 992 } |
| 991 | 993 |
| 992 | 994 |
| 993 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 995 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
| 994 // Return address is on the stack. | 996 // Return address is on the stack. |
| 995 __ pop(LoadIC_TempRegister()); | 997 LoadIC_PushArgs(masm); |
| 996 __ push(ReceiverRegister()); // receiver | |
| 997 __ push(NameRegister()); // name | |
| 998 __ push(LoadIC_TempRegister()); // return address | |
| 999 | 998 |
| 1000 // Perform tail call to the entry. | 999 // Perform tail call to the entry. |
| 1001 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); | 1000 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); |
| 1002 } | 1001 } |
| 1003 | 1002 |
| 1004 | 1003 |
| 1005 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { | 1004 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { |
| 1006 // Return address is on the stack. | 1005 // Return address is on the stack. |
| 1007 __ IncrementCounter(masm->isolate()->counters()->keyed_load_miss(), 1); | 1006 __ IncrementCounter(masm->isolate()->counters()->keyed_load_miss(), 1); |
| 1008 | 1007 |
| 1009 __ pop(KeyedLoadIC_TempRegister()); | 1008 LoadIC_PushArgs(masm); |
| 1010 __ push(ReceiverRegister()); // receiver | |
| 1011 __ push(NameRegister()); // name | |
| 1012 __ push(KeyedLoadIC_TempRegister()); // return address | |
| 1013 | 1009 |
| 1014 // Perform tail call to the entry. | 1010 // Perform tail call to the entry. |
| 1015 ExternalReference ref = | 1011 ExternalReference ref = |
| 1016 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate()); | 1012 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate()); |
| 1017 __ TailCallExternalReference(ref, 2, 1); | 1013 __ TailCallExternalReference(ref, 2, 1); |
| 1018 } | 1014 } |
| 1019 | 1015 |
| 1020 | 1016 |
| 1021 // IC register specifications | 1017 // IC register specifications |
| 1022 const Register LoadIC::ReceiverRegister() { return edx; } | 1018 const Register LoadIC::ReceiverRegister() { return edx; } |
| 1023 const Register LoadIC::NameRegister() { return ecx; } | 1019 const Register LoadIC::NameRegister() { return ecx; } |
| 1024 | 1020 |
| 1025 | 1021 |
| 1022 const Register StoreIC::ReceiverRegister() { return edx; } |
| 1023 const Register StoreIC::NameRegister() { return ecx; } |
| 1024 const Register StoreIC::ValueRegister() { return eax; } |
| 1025 |
| 1026 |
| 1027 const Register KeyedStoreIC::ReceiverRegister() { |
| 1028 return StoreIC::ReceiverRegister(); |
| 1029 } |
| 1030 |
| 1031 |
| 1032 const Register KeyedStoreIC::NameRegister() { |
| 1033 return StoreIC::NameRegister(); |
| 1034 } |
| 1035 |
| 1036 |
| 1037 const Register KeyedStoreIC::ValueRegister() { |
| 1038 return StoreIC::ValueRegister(); |
| 1039 } |
| 1040 |
| 1041 |
| 1026 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 1042 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
| 1027 // Return address is on the stack. | 1043 // Return address is on the stack. |
| 1028 __ pop(KeyedLoadIC_TempRegister()); | 1044 LoadIC_PushArgs(masm); |
| 1029 __ push(ReceiverRegister()); // receiver | |
| 1030 __ push(NameRegister()); // name | |
| 1031 __ push(KeyedLoadIC_TempRegister()); // return address | |
| 1032 | 1045 |
| 1033 // Perform tail call to the entry. | 1046 // Perform tail call to the entry. |
| 1034 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | 1047 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
| 1035 } | 1048 } |
| 1036 | 1049 |
| 1037 | 1050 |
| 1038 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { | 1051 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 1039 // ----------- S t a t e ------------- | 1052 // Return address is on the stack. |
| 1040 // -- eax : value | |
| 1041 // -- ecx : name | |
| 1042 // -- edx : receiver | |
| 1043 // -- esp[0] : return address | |
| 1044 // ----------------------------------- | |
| 1045 Code::Flags flags = Code::ComputeHandlerFlags(Code::STORE_IC); | 1053 Code::Flags flags = Code::ComputeHandlerFlags(Code::STORE_IC); |
| 1046 masm->isolate()->stub_cache()->GenerateProbe( | 1054 masm->isolate()->stub_cache()->GenerateProbe( |
| 1047 masm, flags, edx, ecx, ebx, no_reg); | 1055 masm, flags, ReceiverRegister(), NameRegister(), |
| 1056 ebx, no_reg); |
| 1048 | 1057 |
| 1049 // Cache miss: Jump to runtime. | 1058 // Cache miss: Jump to runtime. |
| 1050 GenerateMiss(masm); | 1059 GenerateMiss(masm); |
| 1051 } | 1060 } |
| 1052 | 1061 |
| 1053 | 1062 |
| 1054 void StoreIC::GenerateMiss(MacroAssembler* masm) { | 1063 static void StoreIC_PushArgs(MacroAssembler* masm) { |
| 1055 // ----------- S t a t e ------------- | 1064 Register receiver = StoreIC::ReceiverRegister(); |
| 1056 // -- eax : value | 1065 Register name = StoreIC::NameRegister(); |
| 1057 // -- ecx : name | 1066 Register value = StoreIC::ValueRegister(); |
| 1058 // -- edx : receiver | 1067 |
| 1059 // -- esp[0] : return address | 1068 ASSERT(!ebx.is(receiver) && !ebx.is(name) && !ebx.is(value)); |
| 1060 // ----------------------------------- | |
| 1061 | 1069 |
| 1062 __ pop(ebx); | 1070 __ pop(ebx); |
| 1063 __ push(edx); | 1071 __ push(receiver); |
| 1064 __ push(ecx); | 1072 __ push(name); |
| 1065 __ push(eax); | 1073 __ push(value); |
| 1066 __ push(ebx); | 1074 __ push(ebx); |
| 1075 } |
| 1076 |
| 1077 |
| 1078 void StoreIC::GenerateMiss(MacroAssembler* masm) { |
| 1079 // Return address is on the stack. |
| 1080 StoreIC_PushArgs(masm); |
| 1067 | 1081 |
| 1068 // Perform tail call to the entry. | 1082 // Perform tail call to the entry. |
| 1069 ExternalReference ref = | 1083 ExternalReference ref = |
| 1070 ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate()); | 1084 ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate()); |
| 1071 __ TailCallExternalReference(ref, 3, 1); | 1085 __ TailCallExternalReference(ref, 3, 1); |
| 1072 } | 1086 } |
| 1073 | 1087 |
| 1074 | 1088 |
| 1075 void StoreIC::GenerateNormal(MacroAssembler* masm) { | 1089 void StoreIC::GenerateNormal(MacroAssembler* masm) { |
| 1076 // ----------- S t a t e ------------- | 1090 // Return address is on the stack. |
| 1077 // -- eax : value | 1091 Label miss, restore_miss; |
| 1078 // -- ecx : name | 1092 Register receiver = ReceiverRegister(); |
| 1079 // -- edx : receiver | 1093 Register name = NameRegister(); |
| 1080 // -- esp[0] : return address | 1094 Register value = ValueRegister(); |
| 1081 // ----------------------------------- | |
| 1082 | 1095 |
| 1083 Label miss, restore_miss; | 1096 GenerateNameDictionaryReceiverCheck(masm, receiver, ebx, edi, &miss); |
| 1084 | |
| 1085 GenerateNameDictionaryReceiverCheck(masm, edx, ebx, edi, &miss); | |
| 1086 | 1097 |
| 1087 // A lot of registers are needed for storing to slow case | 1098 // A lot of registers are needed for storing to slow case |
| 1088 // objects. Push and restore receiver but rely on | 1099 // objects. Push and restore receiver but rely on |
| 1089 // GenerateDictionaryStore preserving the value and name. | 1100 // GenerateDictionaryStore preserving the value and name. |
| 1090 __ push(edx); | 1101 __ push(receiver); |
| 1091 GenerateDictionaryStore(masm, &restore_miss, ebx, ecx, eax, edx, edi); | 1102 GenerateDictionaryStore(masm, &restore_miss, ebx, name, value, receiver, edi); |
| 1092 __ Drop(1); | 1103 __ Drop(1); |
| 1093 Counters* counters = masm->isolate()->counters(); | 1104 Counters* counters = masm->isolate()->counters(); |
| 1094 __ IncrementCounter(counters->store_normal_hit(), 1); | 1105 __ IncrementCounter(counters->store_normal_hit(), 1); |
| 1095 __ ret(0); | 1106 __ ret(0); |
| 1096 | 1107 |
| 1097 __ bind(&restore_miss); | 1108 __ bind(&restore_miss); |
| 1098 __ pop(edx); | 1109 __ pop(receiver); |
| 1099 | 1110 |
| 1100 __ bind(&miss); | 1111 __ bind(&miss); |
| 1101 __ IncrementCounter(counters->store_normal_miss(), 1); | 1112 __ IncrementCounter(counters->store_normal_miss(), 1); |
| 1102 GenerateMiss(masm); | 1113 GenerateMiss(masm); |
| 1103 } | 1114 } |
| 1104 | 1115 |
| 1105 | 1116 |
| 1106 void StoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, | 1117 void StoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, |
| 1107 StrictMode strict_mode) { | 1118 StrictMode strict_mode) { |
| 1108 // ----------- S t a t e ------------- | 1119 // Return address is on the stack. |
| 1109 // -- eax : value | 1120 ASSERT(!ebx.is(ReceiverRegister()) && !ebx.is(NameRegister()) && |
| 1110 // -- ecx : name | 1121 !ebx.is(ValueRegister())); |
| 1111 // -- edx : receiver | |
| 1112 // -- esp[0] : return address | |
| 1113 // ----------------------------------- | |
| 1114 __ pop(ebx); | 1122 __ pop(ebx); |
| 1115 __ push(edx); | 1123 __ push(ReceiverRegister()); |
| 1116 __ push(ecx); | 1124 __ push(NameRegister()); |
| 1117 __ push(eax); | 1125 __ push(ValueRegister()); |
| 1118 __ push(Immediate(Smi::FromInt(strict_mode))); | 1126 __ push(Immediate(Smi::FromInt(strict_mode))); |
| 1119 __ push(ebx); // return address | 1127 __ push(ebx); // return address |
| 1120 | 1128 |
| 1121 // Do tail-call to runtime routine. | 1129 // Do tail-call to runtime routine. |
| 1122 __ TailCallRuntime(Runtime::kSetProperty, 4, 1); | 1130 __ TailCallRuntime(Runtime::kSetProperty, 4, 1); |
| 1123 } | 1131 } |
| 1124 | 1132 |
| 1125 | 1133 |
| 1126 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, | 1134 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, |
| 1127 StrictMode strict_mode) { | 1135 StrictMode strict_mode) { |
| 1128 // ----------- S t a t e ------------- | 1136 // Return address is on the stack. |
| 1129 // -- eax : value | 1137 ASSERT(!ebx.is(ReceiverRegister()) && !ebx.is(NameRegister()) && |
| 1130 // -- ecx : key | 1138 !ebx.is(ValueRegister())); |
| 1131 // -- edx : receiver | |
| 1132 // -- esp[0] : return address | |
| 1133 // ----------------------------------- | |
| 1134 | |
| 1135 __ pop(ebx); | 1139 __ pop(ebx); |
| 1136 __ push(edx); | 1140 __ push(ReceiverRegister()); |
| 1137 __ push(ecx); | 1141 __ push(NameRegister()); |
| 1138 __ push(eax); | 1142 __ push(ValueRegister()); |
| 1139 __ push(Immediate(Smi::FromInt(strict_mode))); // Strict mode. | 1143 __ push(Immediate(Smi::FromInt(strict_mode))); |
| 1140 __ push(ebx); // return address | 1144 __ push(ebx); // return address |
| 1141 | 1145 |
| 1142 // Do tail-call to runtime routine. | 1146 // Do tail-call to runtime routine. |
| 1143 __ TailCallRuntime(Runtime::kSetProperty, 4, 1); | 1147 __ TailCallRuntime(Runtime::kSetProperty, 4, 1); |
| 1144 } | 1148 } |
| 1145 | 1149 |
| 1146 | 1150 |
| 1147 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { | 1151 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { |
| 1148 // ----------- S t a t e ------------- | 1152 // Return address is on the stack. |
| 1149 // -- eax : value | 1153 StoreIC_PushArgs(masm); |
| 1150 // -- ecx : key | |
| 1151 // -- edx : receiver | |
| 1152 // -- esp[0] : return address | |
| 1153 // ----------------------------------- | |
| 1154 | |
| 1155 __ pop(ebx); | |
| 1156 __ push(edx); | |
| 1157 __ push(ecx); | |
| 1158 __ push(eax); | |
| 1159 __ push(ebx); | |
| 1160 | 1154 |
| 1161 // Do tail-call to runtime routine. | 1155 // Do tail-call to runtime routine. |
| 1162 ExternalReference ref = | 1156 ExternalReference ref = |
| 1163 ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate()); | 1157 ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate()); |
| 1164 __ TailCallExternalReference(ref, 3, 1); | 1158 __ TailCallExternalReference(ref, 3, 1); |
| 1165 } | 1159 } |
| 1166 | 1160 |
| 1167 | 1161 |
| 1168 void StoreIC::GenerateSlow(MacroAssembler* masm) { | 1162 void StoreIC::GenerateSlow(MacroAssembler* masm) { |
| 1169 // ----------- S t a t e ------------- | 1163 // Return address is on the stack. |
| 1170 // -- eax : value | 1164 StoreIC_PushArgs(masm); |
| 1171 // -- ecx : key | |
| 1172 // -- edx : receiver | |
| 1173 // -- esp[0] : return address | |
| 1174 // ----------------------------------- | |
| 1175 | |
| 1176 __ pop(ebx); | |
| 1177 __ push(edx); | |
| 1178 __ push(ecx); | |
| 1179 __ push(eax); | |
| 1180 __ push(ebx); // return address | |
| 1181 | 1165 |
| 1182 // Do tail-call to runtime routine. | 1166 // Do tail-call to runtime routine. |
| 1183 ExternalReference ref(IC_Utility(kStoreIC_Slow), masm->isolate()); | 1167 ExternalReference ref(IC_Utility(kStoreIC_Slow), masm->isolate()); |
| 1184 __ TailCallExternalReference(ref, 3, 1); | 1168 __ TailCallExternalReference(ref, 3, 1); |
| 1185 } | 1169 } |
| 1186 | 1170 |
| 1187 | 1171 |
| 1188 void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) { | 1172 void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) { |
| 1189 // ----------- S t a t e ------------- | 1173 // Return address is on the stack. |
| 1190 // -- eax : value | 1174 StoreIC_PushArgs(masm); |
| 1191 // -- ecx : key | |
| 1192 // -- edx : receiver | |
| 1193 // -- esp[0] : return address | |
| 1194 // ----------------------------------- | |
| 1195 | |
| 1196 __ pop(ebx); | |
| 1197 __ push(edx); | |
| 1198 __ push(ecx); | |
| 1199 __ push(eax); | |
| 1200 __ push(ebx); // return address | |
| 1201 | 1175 |
| 1202 // Do tail-call to runtime routine. | 1176 // Do tail-call to runtime routine. |
| 1203 ExternalReference ref(IC_Utility(kKeyedStoreIC_Slow), masm->isolate()); | 1177 ExternalReference ref(IC_Utility(kKeyedStoreIC_Slow), masm->isolate()); |
| 1204 __ TailCallExternalReference(ref, 3, 1); | 1178 __ TailCallExternalReference(ref, 3, 1); |
| 1205 } | 1179 } |
| 1206 | 1180 |
| 1207 | 1181 |
| 1208 #undef __ | 1182 #undef __ |
| 1209 | 1183 |
| 1210 | 1184 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1272 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) | 1246 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) |
| 1273 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 1247 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
| 1274 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 1248 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
| 1275 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1249 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
| 1276 } | 1250 } |
| 1277 | 1251 |
| 1278 | 1252 |
| 1279 } } // namespace v8::internal | 1253 } } // namespace v8::internal |
| 1280 | 1254 |
| 1281 #endif // V8_TARGET_ARCH_X87 | 1255 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |