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/code-stubs.h" | 5 #include "src/code-stubs.h" |
6 | 6 |
7 #include "src/bailout-reason.h" | 7 #include "src/bailout-reason.h" |
8 #include "src/crankshaft/hydrogen.h" | 8 #include "src/crankshaft/hydrogen.h" |
9 #include "src/crankshaft/lithium.h" | 9 #include "src/crankshaft/lithium.h" |
10 #include "src/field-index.h" | 10 #include "src/field-index.h" |
(...skipping 864 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
875 has_object_elements.End(); | 875 has_object_elements.End(); |
876 } | 876 } |
877 has_smi_elements.End(); | 877 has_smi_elements.End(); |
878 | 878 |
879 return environment()->Pop(); | 879 return environment()->Pop(); |
880 } | 880 } |
881 | 881 |
882 Handle<Code> FastArrayPushStub::GenerateCode() { return DoGenerateCode(this); } | 882 Handle<Code> FastArrayPushStub::GenerateCode() { return DoGenerateCode(this); } |
883 | 883 |
884 template <> | 884 template <> |
| 885 HValue* CodeStubGraphBuilder<FastFunctionBindStub>::BuildCodeStub() { |
| 886 // TODO(verwaest): Fix deoptimizer messages. |
| 887 HValue* argc = GetArgumentsLength(); |
| 888 HInstruction* argument_elements = Add<HArgumentsElements>(false, false); |
| 889 HInstruction* object = Add<HAccessArgumentsAt>(argument_elements, argc, |
| 890 graph()->GetConstantMinus1()); |
| 891 BuildCheckHeapObject(object); |
| 892 HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap()); |
| 893 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_JS_FUNCTION); |
| 894 |
| 895 // Disallow binding of slow-mode functions. We need to figure out whether the |
| 896 // length and name property are in the original state. |
| 897 { |
| 898 HValue* bit_field3 = |
| 899 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField3()); |
| 900 HValue* mask = Add<HConstant>(static_cast<int>(Map::DictionaryMap::kMask)); |
| 901 HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, bit_field3, mask); |
| 902 IfBuilder check(this); |
| 903 check.If<HCompareNumericAndBranch>(bit, mask, Token::EQ); |
| 904 check.ThenDeopt(Deoptimizer::kFastFunctionBindFailed); |
| 905 check.End(); |
| 906 } |
| 907 |
| 908 // Check whether the length and name properties are still present as |
| 909 // AccessorInfo objects. In that case, their value can be recomputed even if |
| 910 // the actual value on the object changes. |
| 911 { |
| 912 HValue* descriptors = |
| 913 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapDescriptors()); |
| 914 |
| 915 HValue* descriptors_length = Add<HLoadNamedField>( |
| 916 descriptors, nullptr, HObjectAccess::ForFixedArrayLength()); |
| 917 IfBuilder range(this); |
| 918 range.If<HCompareNumericAndBranch>(descriptors_length, |
| 919 graph()->GetConstant1(), Token::LTE); |
| 920 range.ThenDeopt(Deoptimizer::kFastFunctionBindFailed); |
| 921 range.End(); |
| 922 |
| 923 // Verify .length. |
| 924 const int length_index = JSFunction::kLengthDescriptorIndex; |
| 925 HValue* maybe_length = Add<HLoadKeyed>( |
| 926 descriptors, Add<HConstant>(DescriptorArray::ToKeyIndex(length_index)), |
| 927 nullptr, nullptr, FAST_ELEMENTS); |
| 928 Unique<Name> length_string = Unique<Name>::CreateUninitialized( |
| 929 isolate()->factory()->length_string()); |
| 930 Add<HCheckValue>(maybe_length, length_string, false); |
| 931 |
| 932 HValue* maybe_length_accessor = Add<HLoadKeyed>( |
| 933 descriptors, |
| 934 Add<HConstant>(DescriptorArray::ToValueIndex(length_index)), nullptr, |
| 935 nullptr, FAST_ELEMENTS); |
| 936 BuildCheckHeapObject(maybe_length_accessor); |
| 937 Add<HCheckMaps>(maybe_length_accessor, |
| 938 isolate()->factory()->accessor_info_map()); |
| 939 |
| 940 // Verify .name. |
| 941 const int name_index = JSFunction::kNameDescriptorIndex; |
| 942 HValue* maybe_name = Add<HLoadKeyed>( |
| 943 descriptors, Add<HConstant>(DescriptorArray::ToKeyIndex(name_index)), |
| 944 nullptr, nullptr, FAST_ELEMENTS); |
| 945 Unique<Name> name_string = |
| 946 Unique<Name>::CreateUninitialized(isolate()->factory()->name_string()); |
| 947 Add<HCheckValue>(maybe_name, name_string, false); |
| 948 |
| 949 HValue* maybe_name_accessor = Add<HLoadKeyed>( |
| 950 descriptors, Add<HConstant>(DescriptorArray::ToValueIndex(name_index)), |
| 951 nullptr, nullptr, FAST_ELEMENTS); |
| 952 BuildCheckHeapObject(maybe_name_accessor); |
| 953 Add<HCheckMaps>(maybe_name_accessor, |
| 954 isolate()->factory()->accessor_info_map()); |
| 955 } |
| 956 |
| 957 // Choose the right bound function map based on whether the target is |
| 958 // constructable. |
| 959 { |
| 960 HValue* bit_field = |
| 961 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField()); |
| 962 HValue* mask = Add<HConstant>(static_cast<int>(1 << Map::kIsConstructor)); |
| 963 HValue* bits = AddUncasted<HBitwise>(Token::BIT_AND, bit_field, mask); |
| 964 |
| 965 HValue* native_context = BuildGetNativeContext(); |
| 966 IfBuilder is_constructor(this); |
| 967 is_constructor.If<HCompareNumericAndBranch>(bits, mask, Token::EQ); |
| 968 is_constructor.Then(); |
| 969 { |
| 970 HValue* map = Add<HLoadNamedField>( |
| 971 native_context, nullptr, |
| 972 HObjectAccess::ForContextSlot( |
| 973 Context::BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX)); |
| 974 environment()->Push(map); |
| 975 } |
| 976 is_constructor.Else(); |
| 977 { |
| 978 HValue* map = Add<HLoadNamedField>( |
| 979 native_context, nullptr, |
| 980 HObjectAccess::ForContextSlot( |
| 981 Context::BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX)); |
| 982 environment()->Push(map); |
| 983 } |
| 984 is_constructor.End(); |
| 985 } |
| 986 HValue* bound_function_map = environment()->Pop(); |
| 987 |
| 988 // Verify that __proto__ matches that of a the target bound function. |
| 989 { |
| 990 HValue* prototype = |
| 991 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForPrototype()); |
| 992 HValue* expected_prototype = Add<HLoadNamedField>( |
| 993 bound_function_map, nullptr, HObjectAccess::ForPrototype()); |
| 994 IfBuilder equal_prototype(this); |
| 995 equal_prototype.IfNot<HCompareObjectEqAndBranch>(prototype, |
| 996 expected_prototype); |
| 997 equal_prototype.ThenDeopt(Deoptimizer::kFastFunctionBindFailed); |
| 998 equal_prototype.End(); |
| 999 } |
| 1000 |
| 1001 // Allocate the arguments array. |
| 1002 IfBuilder empty_args(this); |
| 1003 empty_args.If<HCompareNumericAndBranch>(argc, graph()->GetConstant1(), |
| 1004 Token::LTE); |
| 1005 empty_args.Then(); |
| 1006 { environment()->Push(Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex)); } |
| 1007 empty_args.Else(); |
| 1008 { |
| 1009 HValue* elements_length = AddUncasted<HSub>(argc, graph()->GetConstant1()); |
| 1010 HValue* elements = |
| 1011 BuildAllocateAndInitializeArray(FAST_ELEMENTS, elements_length); |
| 1012 |
| 1013 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); |
| 1014 HValue* start = graph()->GetConstant1(); |
| 1015 HValue* key = builder.BeginBody(start, argc, Token::LT); |
| 1016 { |
| 1017 HValue* argument = Add<HAccessArgumentsAt>(argument_elements, argc, key); |
| 1018 HValue* index = AddUncasted<HSub>(key, graph()->GetConstant1()); |
| 1019 AddElementAccess(elements, index, argument, elements, nullptr, |
| 1020 FAST_ELEMENTS, STORE); |
| 1021 } |
| 1022 builder.EndBody(); |
| 1023 environment()->Push(elements); |
| 1024 } |
| 1025 empty_args.End(); |
| 1026 HValue* elements = environment()->Pop(); |
| 1027 |
| 1028 // Find the 'this' to bind. |
| 1029 IfBuilder no_receiver(this); |
| 1030 no_receiver.If<HCompareNumericAndBranch>(argc, graph()->GetConstant0(), |
| 1031 Token::EQ); |
| 1032 no_receiver.Then(); |
| 1033 { environment()->Push(Add<HLoadRoot>(Heap::kUndefinedValueRootIndex)); } |
| 1034 no_receiver.Else(); |
| 1035 { |
| 1036 environment()->Push(Add<HAccessArgumentsAt>(argument_elements, argc, |
| 1037 graph()->GetConstant0())); |
| 1038 } |
| 1039 no_receiver.End(); |
| 1040 HValue* receiver = environment()->Pop(); |
| 1041 |
| 1042 // Allocate the resulting bound function. |
| 1043 HValue* size = Add<HConstant>(JSBoundFunction::kSize); |
| 1044 HValue* bound_function = |
| 1045 Add<HAllocate>(size, HType::JSObject(), NOT_TENURED, |
| 1046 JS_BOUND_FUNCTION_TYPE, graph()->GetConstant0()); |
| 1047 Add<HStoreNamedField>(bound_function, HObjectAccess::ForMap(), |
| 1048 bound_function_map); |
| 1049 HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex); |
| 1050 Add<HStoreNamedField>(bound_function, HObjectAccess::ForPropertiesPointer(), |
| 1051 empty_fixed_array); |
| 1052 Add<HStoreNamedField>(bound_function, HObjectAccess::ForElementsPointer(), |
| 1053 empty_fixed_array); |
| 1054 Add<HStoreNamedField>(bound_function, HObjectAccess::ForBoundTargetFunction(), |
| 1055 object); |
| 1056 |
| 1057 Add<HStoreNamedField>(bound_function, HObjectAccess::ForBoundThis(), |
| 1058 receiver); |
| 1059 Add<HStoreNamedField>(bound_function, HObjectAccess::ForBoundArguments(), |
| 1060 elements); |
| 1061 |
| 1062 return bound_function; |
| 1063 } |
| 1064 |
| 1065 Handle<Code> FastFunctionBindStub::GenerateCode() { |
| 1066 return DoGenerateCode(this); |
| 1067 } |
| 1068 |
| 1069 template <> |
885 HValue* CodeStubGraphBuilder<GrowArrayElementsStub>::BuildCodeStub() { | 1070 HValue* CodeStubGraphBuilder<GrowArrayElementsStub>::BuildCodeStub() { |
886 ElementsKind kind = casted_stub()->elements_kind(); | 1071 ElementsKind kind = casted_stub()->elements_kind(); |
887 if (IsFastDoubleElementsKind(kind)) { | 1072 if (IsFastDoubleElementsKind(kind)) { |
888 info()->MarkAsSavesCallerDoubles(); | 1073 info()->MarkAsSavesCallerDoubles(); |
889 } | 1074 } |
890 | 1075 |
891 HValue* object = GetParameter(GrowArrayElementsDescriptor::kObjectIndex); | 1076 HValue* object = GetParameter(GrowArrayElementsDescriptor::kObjectIndex); |
892 HValue* key = GetParameter(GrowArrayElementsDescriptor::kKeyIndex); | 1077 HValue* key = GetParameter(GrowArrayElementsDescriptor::kKeyIndex); |
893 | 1078 |
894 HValue* elements = AddLoadElements(object); | 1079 HValue* elements = AddLoadElements(object); |
(...skipping 1296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2191 return Pop(); | 2376 return Pop(); |
2192 } | 2377 } |
2193 | 2378 |
2194 | 2379 |
2195 Handle<Code> KeyedLoadGenericStub::GenerateCode() { | 2380 Handle<Code> KeyedLoadGenericStub::GenerateCode() { |
2196 return DoGenerateCode(this); | 2381 return DoGenerateCode(this); |
2197 } | 2382 } |
2198 | 2383 |
2199 } // namespace internal | 2384 } // namespace internal |
2200 } // namespace v8 | 2385 } // namespace v8 |
OLD | NEW |