 Chromium Code Reviews
 Chromium Code Reviews| 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 } | |
| 886 } | 898 } | 
| 887 is_valid.Else(); | 899 is_valid.Else(); | 
| 888 { | 900 { | 
| 889 HValue* result = UnmappedCase(elements, key); | 901 HValue* result = UnmappedCase(elements, key, value); | 
| 890 environment()->Push(result); | 902 if (is_load) environment()->Push(result); | 
| 
Jakob Kummerow
2015/05/28 11:55:00
Doesn't the store stub need to return the value to
 
mvstanton
2015/05/28 13:23:52
Good idea, it's much cleaner that way.
 | |
| 891 } | 903 } | 
| 892 is_valid.End(); | 904 is_valid.End(); | 
| 893 } | 905 } | 
| 894 in_range.Else(); | 906 in_range.Else(); | 
| 895 { | 907 { | 
| 896 HValue* result = UnmappedCase(elements, key); | 908 HValue* result = UnmappedCase(elements, key, value); | 
| 897 environment()->Push(result); | 909 if (is_load) environment()->Push(result); | 
| 898 } | 910 } | 
| 899 in_range.End(); | 911 in_range.End(); | 
| 900 | 912 | 
| 901 return environment()->Pop(); | 913 return is_load ? environment()->Pop() : NULL; | 
| 902 } | 914 } | 
| 903 | 915 | 
| 904 | 916 | 
| 917 template <> | |
| 918 HValue* CodeStubGraphBuilder<KeyedLoadSloppyArgumentsStub>::BuildCodeStub() { | |
| 919 HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex); | |
| 920 HValue* key = GetParameter(LoadDescriptor::kNameIndex); | |
| 921 | |
| 922 return EmitKeyedSloppyArguments(receiver, key, NULL); | |
| 923 } | |
| 924 | |
| 925 | |
| 905 Handle<Code> KeyedLoadSloppyArgumentsStub::GenerateCode() { | 926 Handle<Code> KeyedLoadSloppyArgumentsStub::GenerateCode() { | 
| 906 return DoGenerateCode(this); | 927 return DoGenerateCode(this); | 
| 907 } | 928 } | 
| 908 | 929 | 
| 909 | 930 | 
| 931 template <> | |
| 932 HValue* CodeStubGraphBuilder<KeyedStoreSloppyArgumentsStub>::BuildCodeStub() { | |
| 933 HValue* receiver = GetParameter(StoreDescriptor::kReceiverIndex); | |
| 934 HValue* key = GetParameter(StoreDescriptor::kNameIndex); | |
| 935 HValue* value = GetParameter(StoreDescriptor::kValueIndex); | |
| 936 | |
| 937 EmitKeyedSloppyArguments(receiver, key, value); | |
| 938 return 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 |