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

Side by Side Diff: src/code-stubs-hydrogen.cc

Issue 2044113002: Turn Function.prototype.bind into a hydrogen stub optimized for the common case (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: arm64 Created 4 years, 6 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
« no previous file with comments | « src/code-stubs.h ('k') | src/crankshaft/hydrogen-instructions.h » ('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/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
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
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
OLDNEW
« no previous file with comments | « src/code-stubs.h ('k') | src/crankshaft/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698