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

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

Issue 10991012: Fix 2346: Generic KeyedStoreIC doesn't change length and element_kind atomically (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Review feedback Created 8 years, 2 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 | « no previous file | no next file » | 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 // 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 729 matching lines...) Expand 10 before | Expand all | Expand 10 after
740 __ mov(unmapped_location, eax); 740 __ mov(unmapped_location, eax);
741 __ lea(edi, unmapped_location); 741 __ lea(edi, unmapped_location);
742 __ mov(edx, eax); 742 __ mov(edx, eax);
743 __ RecordWrite(ebx, edi, edx, kDontSaveFPRegs); 743 __ RecordWrite(ebx, edi, edx, kDontSaveFPRegs);
744 __ Ret(); 744 __ Ret();
745 __ bind(&slow); 745 __ bind(&slow);
746 GenerateMiss(masm, false); 746 GenerateMiss(masm, false);
747 } 747 }
748 748
749 749
750 static void KeyedStoreGenerateGenericHelper(MacroAssembler* masm,
751 Label* fast_object,
752 Label* fast_double,
753 Label* slow,
754 bool check_map,
755 bool increment_length) {
756 Label transition_smi_elements;
757 Label finish_object_store, non_double_value, transition_double_elements;
758 Label fast_double_without_map_check;
759 // eax: value
760 // ecx: key (a smi)
761 // edx: receiver
762 // ebx: FixedArray receiver->elements
763 // edi: receiver map
764 // Fast case: Do the store, could either Object or double.
765 __ bind(fast_object);
766 if (check_map) {
767 __ mov(edi, FieldOperand(ebx, HeapObject::kMapOffset));
768 __ cmp(edi, masm->isolate()->factory()->fixed_array_map());
769 __ j(not_equal, fast_double);
770 }
771 // Smi stores don't require further checks.
772 Label non_smi_value;
773 __ JumpIfNotSmi(eax, &non_smi_value);
774 if (increment_length) {
775 // Add 1 to receiver->length.
776 __ add(FieldOperand(edx, JSArray::kLengthOffset),
777 Immediate(Smi::FromInt(1)));
778 }
779 // It's irrelevant whether array is smi-only or not when writing a smi.
780 __ mov(CodeGenerator::FixedArrayElementOperand(ebx, ecx), eax);
781 __ ret(0);
782
783 __ bind(&non_smi_value);
784 // Escape to elements kind transition case.
785 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
786 __ CheckFastObjectElements(edi, &transition_smi_elements);
787
788 // Fast elements array, store the value to the elements backing store.
789 __ bind(&finish_object_store);
790 if (increment_length) {
791 // Add 1 to receiver->length.
792 __ add(FieldOperand(edx, JSArray::kLengthOffset),
793 Immediate(Smi::FromInt(1)));
794 }
795 __ mov(CodeGenerator::FixedArrayElementOperand(ebx, ecx), eax);
796 // Update write barrier for the elements array address.
797 __ mov(edx, eax); // Preserve the value which is returned.
798 __ RecordWriteArray(
799 ebx, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
800 __ ret(0);
801
802 __ bind(fast_double);
803 if (check_map) {
804 // Check for fast double array case. If this fails, call through to the
805 // runtime.
806 __ cmp(edi, masm->isolate()->factory()->fixed_double_array_map());
807 __ j(not_equal, slow);
808 // If the value is a number, store it as a double in the FastDoubleElements
809 // array.
810 }
811 __ bind(&fast_double_without_map_check);
812 __ StoreNumberToDoubleElements(eax, ebx, ecx, edi, xmm0,
813 &transition_double_elements, false);
814 if (increment_length) {
815 // Add 1 to receiver->length.
816 __ add(FieldOperand(edx, JSArray::kLengthOffset),
817 Immediate(Smi::FromInt(1)));
818 }
819 __ ret(0);
820
821 __ bind(&transition_smi_elements);
822 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
823
824 // Transition the array appropriately depending on the value type.
825 __ CheckMap(eax,
826 masm->isolate()->factory()->heap_number_map(),
827 &non_double_value,
828 DONT_DO_SMI_CHECK);
829
830 // Value is a double. Transition FAST_SMI_ELEMENTS -> FAST_DOUBLE_ELEMENTS
831 // and complete the store.
832 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
833 FAST_DOUBLE_ELEMENTS,
834 ebx,
835 edi,
836 slow);
837 ElementsTransitionGenerator::GenerateSmiToDouble(masm, slow);
838 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
839 __ jmp(&fast_double_without_map_check);
840
841 __ bind(&non_double_value);
842 // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS
843 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
844 FAST_ELEMENTS,
845 ebx,
846 edi,
847 slow);
848 ElementsTransitionGenerator::GenerateMapChangeElementsTransition(masm);
849 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
850 __ jmp(&finish_object_store);
851
852 __ bind(&transition_double_elements);
853 // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a
854 // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and
855 // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS
856 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
857 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS,
858 FAST_ELEMENTS,
859 ebx,
860 edi,
861 slow);
862 ElementsTransitionGenerator::GenerateDoubleToObject(masm, slow);
863 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
864 __ jmp(&finish_object_store);
865 }
866
867
750 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, 868 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
751 StrictModeFlag strict_mode) { 869 StrictModeFlag strict_mode) {
752 // ----------- S t a t e ------------- 870 // ----------- S t a t e -------------
753 // -- eax : value 871 // -- eax : value
754 // -- ecx : key 872 // -- ecx : key
755 // -- edx : receiver 873 // -- edx : receiver
756 // -- esp[0] : return address 874 // -- esp[0] : return address
757 // ----------------------------------- 875 // -----------------------------------
758 Label slow, fast_object_with_map_check, fast_object_without_map_check; 876 Label slow, fast_object, fast_object_grow;
759 Label fast_double_with_map_check, fast_double_without_map_check; 877 Label fast_double, fast_double_grow;
760 Label check_if_double_array, array, extra, transition_smi_elements; 878 Label array, extra, check_if_double_array;
761 Label finish_object_store, non_double_value, transition_double_elements;
762 879
763 // Check that the object isn't a smi. 880 // Check that the object isn't a smi.
764 __ JumpIfSmi(edx, &slow); 881 __ JumpIfSmi(edx, &slow);
765 // Get the map from the receiver. 882 // Get the map from the receiver.
766 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); 883 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
767 // Check that the receiver does not require access checks. We need 884 // Check that the receiver does not require access checks. We need
768 // to do this because this generic stub does not perform map checks. 885 // to do this because this generic stub does not perform map checks.
769 __ test_b(FieldOperand(edi, Map::kBitFieldOffset), 886 __ test_b(FieldOperand(edi, Map::kBitFieldOffset),
770 1 << Map::kIsAccessCheckNeeded); 887 1 << Map::kIsAccessCheckNeeded);
771 __ j(not_zero, &slow); 888 __ j(not_zero, &slow);
772 // Check that the key is a smi. 889 // Check that the key is a smi.
773 __ JumpIfNotSmi(ecx, &slow); 890 __ JumpIfNotSmi(ecx, &slow);
774 __ CmpInstanceType(edi, JS_ARRAY_TYPE); 891 __ CmpInstanceType(edi, JS_ARRAY_TYPE);
775 __ j(equal, &array); 892 __ j(equal, &array);
776 // Check that the object is some kind of JSObject. 893 // Check that the object is some kind of JSObject.
777 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); 894 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE);
778 __ j(below, &slow); 895 __ j(below, &slow);
779 896
780 // Object case: Check key against length in the elements array. 897 // Object case: Check key against length in the elements array.
781 // eax: value 898 // eax: value
782 // edx: JSObject 899 // edx: JSObject
783 // ecx: key (a smi) 900 // ecx: key (a smi)
784 // edi: receiver map 901 // edi: receiver map
785 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); 902 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
786 // Check array bounds. Both the key and the length of FixedArray are smis. 903 // Check array bounds. Both the key and the length of FixedArray are smis.
787 __ cmp(ecx, FieldOperand(ebx, FixedArray::kLengthOffset)); 904 __ cmp(ecx, FieldOperand(ebx, FixedArray::kLengthOffset));
788 __ j(below, &fast_object_with_map_check); 905 __ j(below, &fast_object);
789 906
790 // Slow case: call runtime. 907 // Slow case: call runtime.
791 __ bind(&slow); 908 __ bind(&slow);
792 GenerateRuntimeSetProperty(masm, strict_mode); 909 GenerateRuntimeSetProperty(masm, strict_mode);
793 910
794 // Extra capacity case: Check if there is extra capacity to 911 // Extra capacity case: Check if there is extra capacity to
795 // perform the store and update the length. Used for adding one 912 // perform the store and update the length. Used for adding one
796 // element to the array by writing to array[array.length]. 913 // element to the array by writing to array[array.length].
797 __ bind(&extra); 914 __ bind(&extra);
798 // eax: value 915 // eax: value
799 // edx: receiver, a JSArray 916 // edx: receiver, a JSArray
800 // ecx: key, a smi. 917 // ecx: key, a smi.
801 // ebx: receiver->elements, a FixedArray 918 // ebx: receiver->elements, a FixedArray
802 // edi: receiver map 919 // edi: receiver map
803 // flags: compare (ecx, edx.length()) 920 // flags: compare (ecx, edx.length())
804 // do not leave holes in the array: 921 // do not leave holes in the array:
805 __ j(not_equal, &slow); 922 __ j(not_equal, &slow);
806 __ cmp(ecx, FieldOperand(ebx, FixedArray::kLengthOffset)); 923 __ cmp(ecx, FieldOperand(ebx, FixedArray::kLengthOffset));
807 __ j(above_equal, &slow); 924 __ j(above_equal, &slow);
808 __ mov(edi, FieldOperand(ebx, HeapObject::kMapOffset)); 925 __ mov(edi, FieldOperand(ebx, HeapObject::kMapOffset));
809 __ cmp(edi, masm->isolate()->factory()->fixed_array_map()); 926 __ cmp(edi, masm->isolate()->factory()->fixed_array_map());
810 __ j(not_equal, &check_if_double_array); 927 __ j(not_equal, &check_if_double_array);
811 // Add 1 to receiver->length, and go to common element store code for Objects. 928 __ jmp(&fast_object_grow);
812 __ add(FieldOperand(edx, JSArray::kLengthOffset),
813 Immediate(Smi::FromInt(1)));
814 __ jmp(&fast_object_without_map_check);
815 929
816 __ bind(&check_if_double_array); 930 __ bind(&check_if_double_array);
817 __ cmp(edi, masm->isolate()->factory()->fixed_double_array_map()); 931 __ cmp(edi, masm->isolate()->factory()->fixed_double_array_map());
818 __ j(not_equal, &slow); 932 __ j(not_equal, &slow);
819 // Add 1 to receiver->length, and go to common element store code for doubles. 933 __ jmp(&fast_double_grow);
820 __ add(FieldOperand(edx, JSArray::kLengthOffset),
821 Immediate(Smi::FromInt(1)));
822 __ jmp(&fast_double_without_map_check);
823 934
824 // Array case: Get the length and the elements array from the JS 935 // Array case: Get the length and the elements array from the JS
825 // array. Check that the array is in fast mode (and writable); if it 936 // array. Check that the array is in fast mode (and writable); if it
826 // is the length is always a smi. 937 // is the length is always a smi.
827 __ bind(&array); 938 __ bind(&array);
828 // eax: value 939 // eax: value
829 // edx: receiver, a JSArray 940 // edx: receiver, a JSArray
830 // ecx: key, a smi. 941 // ecx: key, a smi.
831 // edi: receiver map 942 // edi: receiver map
832 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); 943 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
833 944
834 // Check the key against the length in the array and fall through to the 945 // Check the key against the length in the array and fall through to the
835 // common store code. 946 // common store code.
836 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. 947 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis.
837 __ j(above_equal, &extra); 948 __ j(above_equal, &extra);
838 949
839 // Fast case: Do the store, could either Object or double. 950 KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double, &slow,
840 __ bind(&fast_object_with_map_check); 951 true, false);
841 // eax: value 952 KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow,
842 // ecx: key (a smi) 953 &slow, false, true);
843 // edx: receiver
844 // ebx: FixedArray receiver->elements
845 // edi: receiver map
846 __ mov(edi, FieldOperand(ebx, HeapObject::kMapOffset));
847 __ cmp(edi, masm->isolate()->factory()->fixed_array_map());
848 __ j(not_equal, &fast_double_with_map_check);
849 __ bind(&fast_object_without_map_check);
850 // Smi stores don't require further checks.
851 Label non_smi_value;
852 __ JumpIfNotSmi(eax, &non_smi_value);
853 // It's irrelevant whether array is smi-only or not when writing a smi.
854 __ mov(CodeGenerator::FixedArrayElementOperand(ebx, ecx), eax);
855 __ ret(0);
856
857 __ bind(&non_smi_value);
858 // Escape to elements kind transition case.
859 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
860 __ CheckFastObjectElements(edi, &transition_smi_elements);
861
862 // Fast elements array, store the value to the elements backing store.
863 __ bind(&finish_object_store);
864 __ mov(CodeGenerator::FixedArrayElementOperand(ebx, ecx), eax);
865 // Update write barrier for the elements array address.
866 __ mov(edx, eax); // Preserve the value which is returned.
867 __ RecordWriteArray(
868 ebx, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
869 __ ret(0);
870
871 __ bind(&fast_double_with_map_check);
872 // Check for fast double array case. If this fails, call through to the
873 // runtime.
874 __ cmp(edi, masm->isolate()->factory()->fixed_double_array_map());
875 __ j(not_equal, &slow);
876 __ bind(&fast_double_without_map_check);
877 // If the value is a number, store it as a double in the FastDoubleElements
878 // array.
879 __ StoreNumberToDoubleElements(eax, ebx, ecx, edx, xmm0,
880 &transition_double_elements, false);
881 __ ret(0);
882
883 __ bind(&transition_smi_elements);
884 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
885
886 // Transition the array appropriately depending on the value type.
887 __ CheckMap(eax,
888 masm->isolate()->factory()->heap_number_map(),
889 &non_double_value,
890 DONT_DO_SMI_CHECK);
891
892 // Value is a double. Transition FAST_SMI_ELEMENTS -> FAST_DOUBLE_ELEMENTS
893 // and complete the store.
894 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
895 FAST_DOUBLE_ELEMENTS,
896 ebx,
897 edi,
898 &slow);
899 ElementsTransitionGenerator::GenerateSmiToDouble(masm, &slow);
900 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
901 __ jmp(&fast_double_without_map_check);
902
903 __ bind(&non_double_value);
904 // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS
905 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
906 FAST_ELEMENTS,
907 ebx,
908 edi,
909 &slow);
910 ElementsTransitionGenerator::GenerateMapChangeElementsTransition(masm);
911 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
912 __ jmp(&finish_object_store);
913
914 __ bind(&transition_double_elements);
915 // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a
916 // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and
917 // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS
918 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
919 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS,
920 FAST_ELEMENTS,
921 ebx,
922 edi,
923 &slow);
924 ElementsTransitionGenerator::GenerateDoubleToObject(masm, &slow);
925 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
926 __ jmp(&finish_object_store);
927 } 954 }
928 955
929 956
930 // The generated code does not accept smi keys. 957 // The generated code does not accept smi keys.
931 // The generated code falls through if both probes miss. 958 // The generated code falls through if both probes miss.
932 void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm, 959 void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm,
933 int argc, 960 int argc,
934 Code::Kind kind, 961 Code::Kind kind,
935 Code::ExtraICState extra_state) { 962 Code::ExtraICState extra_state) {
936 // ----------- S t a t e ------------- 963 // ----------- S t a t e -------------
(...skipping 828 matching lines...) Expand 10 before | Expand all | Expand 10 after
1765 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) 1792 Condition cc = (check == ENABLE_INLINED_SMI_CHECK)
1766 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) 1793 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero)
1767 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); 1794 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry);
1768 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); 1795 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc);
1769 } 1796 }
1770 1797
1771 1798
1772 } } // namespace v8::internal 1799 } } // namespace v8::internal
1773 1800
1774 #endif // V8_TARGET_ARCH_IA32 1801 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698