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 #include "src/bailout-reason.h" | 7 #include "src/bailout-reason.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/field-index.h" | 9 #include "src/field-index.h" |
10 #include "src/hydrogen.h" | 10 #include "src/hydrogen.h" |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 void BuildStoreNamedField(HValue* object, HValue* value, FieldIndex index, | 67 void BuildStoreNamedField(HValue* object, HValue* value, FieldIndex index, |
68 Representation representation, | 68 Representation representation, |
69 bool transition_to_field); | 69 bool transition_to_field); |
70 | 70 |
71 enum ArgumentClass { | 71 enum ArgumentClass { |
72 NONE, | 72 NONE, |
73 SINGLE, | 73 SINGLE, |
74 MULTIPLE | 74 MULTIPLE |
75 }; | 75 }; |
76 | 76 |
77 HValue* UnmappedCase(HValue* elements, HValue* key); | 77 HValue* UnmappedCase(HValue* elements, HValue* key, HValue* value); |
| 78 HValue* EmitKeyedSloppyArguments(HValue* receiver, HValue* key, |
| 79 HValue* value); |
78 | 80 |
79 HValue* BuildArrayConstructor(ElementsKind kind, | 81 HValue* BuildArrayConstructor(ElementsKind kind, |
80 AllocationSiteOverrideMode override_mode, | 82 AllocationSiteOverrideMode override_mode, |
81 ArgumentClass argument_class); | 83 ArgumentClass argument_class); |
82 HValue* BuildInternalArrayConstructor(ElementsKind kind, | 84 HValue* BuildInternalArrayConstructor(ElementsKind kind, |
83 ArgumentClass argument_class); | 85 ArgumentClass argument_class); |
84 | 86 |
85 // BuildCheckAndInstallOptimizedCode emits code to install the optimized | 87 // BuildCheckAndInstallOptimizedCode emits code to install the optimized |
86 // function found in the optimized code map at map_index in js_function, if | 88 // function found in the optimized code map at map_index in js_function, if |
87 // the function at map_index matches the given native_context. Builder is | 89 // the function at map_index matches the given native_context. Builder is |
(...skipping 701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
789 HValue* descriptors = Add<HLoadNamedField>(map, nullptr, descriptors_access); | 791 HValue* descriptors = Add<HLoadNamedField>(map, nullptr, descriptors_access); |
790 HObjectAccess value_access = HObjectAccess::ForObservableJSObjectOffset( | 792 HObjectAccess value_access = HObjectAccess::ForObservableJSObjectOffset( |
791 DescriptorArray::GetValueOffset(casted_stub()->constant_index())); | 793 DescriptorArray::GetValueOffset(casted_stub()->constant_index())); |
792 return Add<HLoadNamedField>(descriptors, nullptr, value_access); | 794 return Add<HLoadNamedField>(descriptors, nullptr, value_access); |
793 } | 795 } |
794 | 796 |
795 | 797 |
796 Handle<Code> LoadConstantStub::GenerateCode() { return DoGenerateCode(this); } | 798 Handle<Code> LoadConstantStub::GenerateCode() { return DoGenerateCode(this); } |
797 | 799 |
798 | 800 |
799 HValue* CodeStubGraphBuilderBase::UnmappedCase(HValue* elements, HValue* key) { | 801 HValue* CodeStubGraphBuilderBase::UnmappedCase(HValue* elements, HValue* key, |
800 HValue* result; | 802 HValue* value) { |
| 803 HValue* result = NULL; |
801 HInstruction* backing_store = | 804 HInstruction* backing_store = |
802 Add<HLoadKeyed>(elements, graph()->GetConstant1(), nullptr, FAST_ELEMENTS, | 805 Add<HLoadKeyed>(elements, graph()->GetConstant1(), nullptr, FAST_ELEMENTS, |
803 ALLOW_RETURN_HOLE); | 806 ALLOW_RETURN_HOLE); |
804 Add<HCheckMaps>(backing_store, isolate()->factory()->fixed_array_map()); | 807 Add<HCheckMaps>(backing_store, isolate()->factory()->fixed_array_map()); |
805 HValue* backing_store_length = Add<HLoadNamedField>( | 808 HValue* backing_store_length = Add<HLoadNamedField>( |
806 backing_store, nullptr, HObjectAccess::ForFixedArrayLength()); | 809 backing_store, nullptr, HObjectAccess::ForFixedArrayLength()); |
807 IfBuilder in_unmapped_range(this); | 810 IfBuilder in_unmapped_range(this); |
808 in_unmapped_range.If<HCompareNumericAndBranch>(key, backing_store_length, | 811 in_unmapped_range.If<HCompareNumericAndBranch>(key, backing_store_length, |
809 Token::LT); | 812 Token::LT); |
810 in_unmapped_range.Then(); | 813 in_unmapped_range.Then(); |
811 { | 814 { |
812 result = Add<HLoadKeyed>(backing_store, key, nullptr, FAST_HOLEY_ELEMENTS, | 815 if (value == NULL) { |
813 NEVER_RETURN_HOLE); | 816 result = Add<HLoadKeyed>(backing_store, key, nullptr, FAST_HOLEY_ELEMENTS, |
| 817 NEVER_RETURN_HOLE); |
| 818 } else { |
| 819 Add<HStoreKeyed>(backing_store, key, value, FAST_HOLEY_ELEMENTS); |
| 820 } |
814 } | 821 } |
815 in_unmapped_range.ElseDeopt(Deoptimizer::kOutsideOfRange); | 822 in_unmapped_range.ElseDeopt(Deoptimizer::kOutsideOfRange); |
816 in_unmapped_range.End(); | 823 in_unmapped_range.End(); |
817 return result; | 824 return result; |
818 } | 825 } |
819 | 826 |
820 | 827 |
821 template <> | 828 HValue* CodeStubGraphBuilderBase::EmitKeyedSloppyArguments(HValue* receiver, |
822 HValue* CodeStubGraphBuilder<KeyedLoadSloppyArgumentsStub>::BuildCodeStub() { | 829 HValue* key, |
823 HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex); | 830 HValue* value) { |
824 HValue* key = GetParameter(LoadDescriptor::kNameIndex); | |
825 | |
826 // Mapped arguments are actual arguments. Unmapped arguments are values added | 831 // Mapped arguments are actual arguments. Unmapped arguments are values added |
827 // to the arguments object after it was created for the call. Mapped arguments | 832 // to the arguments object after it was created for the call. Mapped arguments |
828 // are stored in the context at indexes given by elements[key + 2]. Unmapped | 833 // are stored in the context at indexes given by elements[key + 2]. Unmapped |
829 // arguments are stored as regular indexed properties in the arguments array, | 834 // arguments are stored as regular indexed properties in the arguments array, |
830 // held at elements[1]. See NewSloppyArguments() in runtime.cc for a detailed | 835 // held at elements[1]. See NewSloppyArguments() in runtime.cc for a detailed |
831 // look at argument object construction. | 836 // look at argument object construction. |
832 // | 837 // |
833 // The sloppy arguments elements array has a special format: | 838 // The sloppy arguments elements array has a special format: |
834 // | 839 // |
835 // 0: context | 840 // 0: context |
836 // 1: unmapped arguments array | 841 // 1: unmapped arguments array |
837 // 2: mapped_index0, | 842 // 2: mapped_index0, |
838 // 3: mapped_index1, | 843 // 3: mapped_index1, |
839 // ... | 844 // ... |
840 // | 845 // |
841 // length is 2 + min(number_of_actual_arguments, number_of_formal_arguments). | 846 // length is 2 + min(number_of_actual_arguments, number_of_formal_arguments). |
842 // If key + 2 >= elements.length then attempt to look in the unmapped | 847 // If key + 2 >= elements.length then attempt to look in the unmapped |
843 // arguments array (given by elements[1]) and return the value at key, missing | 848 // arguments array (given by elements[1]) and return the value at key, missing |
844 // to the runtime if the unmapped arguments array is not a fixed array or if | 849 // to the runtime if the unmapped arguments array is not a fixed array or if |
845 // key >= unmapped_arguments_array.length. | 850 // key >= unmapped_arguments_array.length. |
846 // | 851 // |
847 // Otherwise, t = elements[key + 2]. If t is the hole, then look up the value | 852 // Otherwise, t = elements[key + 2]. If t is the hole, then look up the value |
848 // in the unmapped arguments array, as described above. Otherwise, t is a Smi | 853 // in the unmapped arguments array, as described above. Otherwise, t is a Smi |
849 // index into the context array given at elements[0]. Return the value at | 854 // index into the context array given at elements[0]. Return the value at |
850 // context[t]. | 855 // context[t]. |
851 | 856 |
| 857 bool is_load = value == NULL; |
| 858 |
852 key = AddUncasted<HForceRepresentation>(key, Representation::Smi()); | 859 key = AddUncasted<HForceRepresentation>(key, Representation::Smi()); |
853 IfBuilder positive_smi(this); | 860 IfBuilder positive_smi(this); |
854 positive_smi.If<HCompareNumericAndBranch>(key, graph()->GetConstant0(), | 861 positive_smi.If<HCompareNumericAndBranch>(key, graph()->GetConstant0(), |
855 Token::LT); | 862 Token::LT); |
856 positive_smi.ThenDeopt(Deoptimizer::kKeyIsNegative); | 863 positive_smi.ThenDeopt(Deoptimizer::kKeyIsNegative); |
857 positive_smi.End(); | 864 positive_smi.End(); |
858 | 865 |
859 HValue* constant_two = Add<HConstant>(2); | 866 HValue* constant_two = Add<HConstant>(2); |
860 HValue* elements = AddLoadElements(receiver, nullptr); | 867 HValue* elements = AddLoadElements(receiver, nullptr); |
861 HValue* elements_length = Add<HLoadNamedField>( | 868 HValue* elements_length = Add<HLoadNamedField>( |
(...skipping 11 matching lines...) Expand all Loading... |
873 is_valid.IfNot<HCompareObjectEqAndBranch>(mapped_index, | 880 is_valid.IfNot<HCompareObjectEqAndBranch>(mapped_index, |
874 graph()->GetConstantHole()); | 881 graph()->GetConstantHole()); |
875 is_valid.Then(); | 882 is_valid.Then(); |
876 { | 883 { |
877 // TODO(mvstanton): I'd like to assert from this point, that if the | 884 // TODO(mvstanton): I'd like to assert from this point, that if the |
878 // mapped_index is not the hole that it is indeed, a smi. An unnecessary | 885 // mapped_index is not the hole that it is indeed, a smi. An unnecessary |
879 // smi check is being emitted. | 886 // smi check is being emitted. |
880 HValue* the_context = Add<HLoadKeyed>(elements, graph()->GetConstant0(), | 887 HValue* the_context = Add<HLoadKeyed>(elements, graph()->GetConstant0(), |
881 nullptr, FAST_ELEMENTS); | 888 nullptr, FAST_ELEMENTS); |
882 STATIC_ASSERT(Context::kHeaderSize == FixedArray::kHeaderSize); | 889 STATIC_ASSERT(Context::kHeaderSize == FixedArray::kHeaderSize); |
883 HValue* result = Add<HLoadKeyed>(the_context, mapped_index, nullptr, | 890 if (is_load) { |
884 FAST_ELEMENTS, ALLOW_RETURN_HOLE); | 891 HValue* result = Add<HLoadKeyed>(the_context, mapped_index, nullptr, |
885 environment()->Push(result); | 892 FAST_ELEMENTS, ALLOW_RETURN_HOLE); |
| 893 environment()->Push(result); |
| 894 } else { |
| 895 DCHECK(value != NULL); |
| 896 Add<HStoreKeyed>(the_context, mapped_index, value, FAST_ELEMENTS); |
| 897 environment()->Push(value); |
| 898 } |
886 } | 899 } |
887 is_valid.Else(); | 900 is_valid.Else(); |
888 { | 901 { |
889 HValue* result = UnmappedCase(elements, key); | 902 HValue* result = UnmappedCase(elements, key, value); |
890 environment()->Push(result); | 903 environment()->Push(is_load ? result : value); |
891 } | 904 } |
892 is_valid.End(); | 905 is_valid.End(); |
893 } | 906 } |
894 in_range.Else(); | 907 in_range.Else(); |
895 { | 908 { |
896 HValue* result = UnmappedCase(elements, key); | 909 HValue* result = UnmappedCase(elements, key, value); |
897 environment()->Push(result); | 910 environment()->Push(is_load ? result : value); |
898 } | 911 } |
899 in_range.End(); | 912 in_range.End(); |
900 | 913 |
901 return environment()->Pop(); | 914 return environment()->Pop(); |
902 } | 915 } |
903 | 916 |
904 | 917 |
| 918 template <> |
| 919 HValue* CodeStubGraphBuilder<KeyedLoadSloppyArgumentsStub>::BuildCodeStub() { |
| 920 HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex); |
| 921 HValue* key = GetParameter(LoadDescriptor::kNameIndex); |
| 922 |
| 923 return EmitKeyedSloppyArguments(receiver, key, NULL); |
| 924 } |
| 925 |
| 926 |
905 Handle<Code> KeyedLoadSloppyArgumentsStub::GenerateCode() { | 927 Handle<Code> KeyedLoadSloppyArgumentsStub::GenerateCode() { |
906 return DoGenerateCode(this); | 928 return DoGenerateCode(this); |
907 } | 929 } |
908 | 930 |
909 | 931 |
| 932 template <> |
| 933 HValue* CodeStubGraphBuilder<KeyedStoreSloppyArgumentsStub>::BuildCodeStub() { |
| 934 HValue* receiver = GetParameter(StoreDescriptor::kReceiverIndex); |
| 935 HValue* key = GetParameter(StoreDescriptor::kNameIndex); |
| 936 HValue* value = GetParameter(StoreDescriptor::kValueIndex); |
| 937 |
| 938 return EmitKeyedSloppyArguments(receiver, key, value); |
| 939 } |
| 940 |
| 941 |
| 942 Handle<Code> KeyedStoreSloppyArgumentsStub::GenerateCode() { |
| 943 return DoGenerateCode(this); |
| 944 } |
| 945 |
| 946 |
910 void CodeStubGraphBuilderBase::BuildStoreNamedField( | 947 void CodeStubGraphBuilderBase::BuildStoreNamedField( |
911 HValue* object, HValue* value, FieldIndex index, | 948 HValue* object, HValue* value, FieldIndex index, |
912 Representation representation, bool transition_to_field) { | 949 Representation representation, bool transition_to_field) { |
913 DCHECK(!index.is_double() || representation.IsDouble()); | 950 DCHECK(!index.is_double() || representation.IsDouble()); |
914 int offset = index.offset(); | 951 int offset = index.offset(); |
915 HObjectAccess access = | 952 HObjectAccess access = |
916 index.is_inobject() | 953 index.is_inobject() |
917 ? HObjectAccess::ForObservableJSObjectOffset(offset, representation) | 954 ? HObjectAccess::ForObservableJSObjectOffset(offset, representation) |
918 : HObjectAccess::ForBackingStoreOffset(offset, representation); | 955 : HObjectAccess::ForBackingStoreOffset(offset, representation); |
919 | 956 |
(...skipping 1279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2199 | 2236 |
2200 return Pop(); | 2237 return Pop(); |
2201 } | 2238 } |
2202 | 2239 |
2203 | 2240 |
2204 Handle<Code> KeyedLoadGenericStub::GenerateCode() { | 2241 Handle<Code> KeyedLoadGenericStub::GenerateCode() { |
2205 return DoGenerateCode(this); | 2242 return DoGenerateCode(this); |
2206 } | 2243 } |
2207 | 2244 |
2208 } } // namespace v8::internal | 2245 } } // namespace v8::internal |
OLD | NEW |