Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(885)

Side by Side Diff: src/ia32/ic-ia32.cc

Issue 381633002: Use a register spec for StoreIC and KeyedStoreIC. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Code comments. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/full-codegen-ia32.cc ('k') | src/ia32/lithium-codegen-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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_IA32 7 #if V8_TARGET_ARCH_IA32
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
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
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, &notin, &slow); 669 GenerateMappedArgumentsLookup(masm, receiver, name, ebx, edi, &notin,
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, kDontSaveFPRegs); 674 __ RecordWrite(ebx, ecx, edx, kDontSaveFPRegs);
681 __ Ret(); 675 __ Ret();
682 __ bind(&notin); 676 __ bind(&notin);
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, kDontSaveFPRegs); 683 __ RecordWrite(ebx, edi, edx, kDontSaveFPRegs);
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, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 757 ebx, edx, key, kDontSaveFPRegs, 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, xmm0, 780 __ StoreNumberToDoubleElements(value, ebx, key, edi, xmm0,
783 &transition_double_elements); 781 &transition_double_elements);
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
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
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_IA32 1255 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/full-codegen-ia32.cc ('k') | src/ia32/lithium-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698