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

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

Issue 1816553002: Introduce a code stub version of Array.prototype.push (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Addressed comments Created 4 years, 9 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/arm/lithium-codegen-arm.cc » ('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 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 CompilationInfo* info() { return info_; } 71 CompilationInfo* info() { return info_; }
72 CodeStub* stub() { return code_stub_; } 72 CodeStub* stub() { return code_stub_; }
73 HContext* context() { return context_; } 73 HContext* context() { return context_; }
74 Isolate* isolate() { return info_->isolate(); } 74 Isolate* isolate() { return info_->isolate(); }
75 75
76 HLoadNamedField* BuildLoadNamedField(HValue* object, FieldIndex index); 76 HLoadNamedField* BuildLoadNamedField(HValue* object, FieldIndex index);
77 void BuildStoreNamedField(HValue* object, HValue* value, FieldIndex index, 77 void BuildStoreNamedField(HValue* object, HValue* value, FieldIndex index,
78 Representation representation, 78 Representation representation,
79 bool transition_to_field); 79 bool transition_to_field);
80 80
81 HValue* BuildPushElement(HValue* object, HValue* value, ElementsKind kind);
82
81 enum ArgumentClass { 83 enum ArgumentClass {
82 NONE, 84 NONE,
83 SINGLE, 85 SINGLE,
84 MULTIPLE 86 MULTIPLE
85 }; 87 };
86 88
87 HValue* UnmappedCase(HValue* elements, HValue* key, HValue* value); 89 HValue* UnmappedCase(HValue* elements, HValue* key, HValue* value);
88 HValue* EmitKeyedSloppyArguments(HValue* receiver, HValue* key, 90 HValue* EmitKeyedSloppyArguments(HValue* receiver, HValue* key,
89 HValue* value); 91 HValue* value);
90 92
(...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after
773 HObjectAccess::ForContextSlot(slot_index), 775 HObjectAccess::ForContextSlot(slot_index),
774 GetParameter(2), STORE_TO_INITIALIZED_ENTRY); 776 GetParameter(2), STORE_TO_INITIALIZED_ENTRY);
775 return GetParameter(2); 777 return GetParameter(2);
776 } 778 }
777 779
778 780
779 Handle<Code> StoreScriptContextFieldStub::GenerateCode() { 781 Handle<Code> StoreScriptContextFieldStub::GenerateCode() {
780 return DoGenerateCode(this); 782 return DoGenerateCode(this);
781 } 783 }
782 784
785 HValue* CodeStubGraphBuilderBase::BuildPushElement(HValue* object,
786 HValue* value,
787 ElementsKind kind) {
788 HValue* length = Add<HLoadNamedField>(object, nullptr,
789 HObjectAccess::ForArrayLength(kind));
790 HValue* key = length;
791 HValue* elements = Add<HLoadNamedField>(object, nullptr,
792 HObjectAccess::ForElementsPointer());
793 elements = BuildCheckForCapacityGrow(object, elements, kind, length, key,
794 true, STORE);
795 AddElementAccess(elements, key, value, object, nullptr, kind, STORE);
796 return key;
797 }
798
799 template <>
800 HValue* CodeStubGraphBuilder<FastArrayPushStub>::BuildCodeStub() {
801 // TODO(verwaest): Fix deoptimizer messages.
802 HValue* argc = GetArgumentsLength();
803 IfBuilder arg_check(this);
804 arg_check.If<HCompareNumericAndBranch>(argc, graph()->GetConstant1(),
805 Token::NE);
806 arg_check.ThenDeopt(Deoptimizer::kFastArrayPushFailed);
807 arg_check.End();
808
809 HInstruction* argument_elements = Add<HArgumentsElements>(false, false);
810 HInstruction* object = Add<HAccessArgumentsAt>(argument_elements, argc,
811 graph()->GetConstantMinus1());
812 HInstruction* value =
813 Add<HAccessArgumentsAt>(argument_elements, argc, graph()->GetConstant0());
814
815 BuildCheckHeapObject(object);
816 HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap());
817 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_JS_ARRAY);
818
819 // Disallow pushing onto prototypes. It might be the JSArray prototype.
820 // Disallow pushing onto non-extensible objects.
821 {
822 HValue* bit_field2 =
823 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2());
824 HValue* mask =
825 Add<HConstant>(static_cast<int>(Map::IsPrototypeMapBits::kMask) |
826 (1 << Map::kIsExtensible));
827 HValue* bits = AddUncasted<HBitwise>(Token::BIT_AND, bit_field2, mask);
828 IfBuilder check(this);
829 check.If<HCompareNumericAndBranch>(
830 bits, Add<HConstant>(1 << Map::kIsExtensible), Token::NE);
831 check.ThenDeopt(Deoptimizer::kFastArrayPushFailed);
832 check.End();
833 }
834
835 // Disallow pushing onto observed objects.
836 {
837 HValue* bit_field =
838 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField());
839 HValue* mask = Add<HConstant>(1 << Map::kIsObserved);
840 HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, bit_field, mask);
841 IfBuilder check(this);
842 check.If<HCompareNumericAndBranch>(bit, mask, Token::EQ);
843 check.ThenDeopt(Deoptimizer::kFastArrayPushFailed);
844 check.End();
845 }
846
847 // Disallow pushing onto arrays in dictionary named property mode. We need to
848 // figure out whether the length property is still writable.
849 {
850 HValue* bit_field3 =
851 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField3());
852 HValue* mask = Add<HConstant>(static_cast<int>(Map::DictionaryMap::kMask));
853 HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, bit_field3, mask);
854 IfBuilder check(this);
855 check.If<HCompareNumericAndBranch>(bit, mask, Token::EQ);
856 check.ThenDeopt(Deoptimizer::kFastArrayPushFailed);
857 check.End();
858 }
859
860 // Check whether the length property is writable. The length property is the
861 // only default named property on arrays. It's nonconfigurable, hence is
862 // guaranteed to stay the first property.
863 {
864 HValue* descriptors =
865 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapDescriptors());
866 HValue* details = Add<HLoadKeyed>(
867 descriptors, Add<HConstant>(DescriptorArray::ToDetailsIndex(0)),
868 nullptr, nullptr, FAST_SMI_ELEMENTS);
869 HValue* mask =
870 Add<HConstant>(READ_ONLY << PropertyDetails::AttributesField::kShift);
871 HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, details, mask);
872 IfBuilder readonly(this);
873 readonly.If<HCompareNumericAndBranch>(bit, mask, Token::EQ);
874 readonly.ThenDeopt(Deoptimizer::kFastArrayPushFailed);
875 readonly.End();
876 }
877
878 HValue* null = Add<HLoadRoot>(Heap::kNullValueRootIndex);
879 HValue* empty = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
880 environment()->Push(map);
881 LoopBuilder check_prototypes(this);
882 check_prototypes.BeginBody(1);
883 {
884 HValue* parent_map = environment()->Pop();
885 HValue* prototype = Add<HLoadNamedField>(parent_map, nullptr,
886 HObjectAccess::ForPrototype());
887
888 IfBuilder is_null(this);
889 is_null.If<HCompareObjectEqAndBranch>(prototype, null);
890 is_null.Then();
891 check_prototypes.Break();
892 is_null.End();
893
894 HValue* prototype_map =
895 Add<HLoadNamedField>(prototype, nullptr, HObjectAccess::ForMap());
896 HValue* instance_type = Add<HLoadNamedField>(
897 prototype_map, nullptr, HObjectAccess::ForMapInstanceType());
898 IfBuilder check_instance_type(this);
899 check_instance_type.If<HCompareNumericAndBranch>(
900 instance_type, Add<HConstant>(LAST_CUSTOM_ELEMENTS_RECEIVER),
901 Token::LTE);
902 check_instance_type.ThenDeopt(Deoptimizer::kFastArrayPushFailed);
903 check_instance_type.End();
904
905 HValue* elements = Add<HLoadNamedField>(
906 prototype, nullptr, HObjectAccess::ForElementsPointer());
907 IfBuilder no_elements(this);
908 no_elements.IfNot<HCompareObjectEqAndBranch>(elements, empty);
909 no_elements.ThenDeopt(Deoptimizer::kFastArrayPushFailed);
910 no_elements.End();
911
912 environment()->Push(prototype_map);
913 }
914 check_prototypes.EndBody();
915
916 HValue* bit_field2 =
917 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2());
918 HValue* kind = BuildDecodeField<Map::ElementsKindBits>(bit_field2);
919
920 // Below we only check the upper bound of the relevant ranges to include both
921 // holey and non-holey versions. We check them in order smi, object, double
922 // since smi < object < double.
923 STATIC_ASSERT(FAST_SMI_ELEMENTS < FAST_HOLEY_SMI_ELEMENTS);
924 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS < FAST_HOLEY_ELEMENTS);
925 STATIC_ASSERT(FAST_ELEMENTS < FAST_HOLEY_ELEMENTS);
926 STATIC_ASSERT(FAST_HOLEY_ELEMENTS < FAST_HOLEY_DOUBLE_ELEMENTS);
927 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FAST_HOLEY_DOUBLE_ELEMENTS);
928 IfBuilder has_smi_elements(this);
929 has_smi_elements.If<HCompareNumericAndBranch>(
930 kind, Add<HConstant>(FAST_HOLEY_SMI_ELEMENTS), Token::LTE);
931 has_smi_elements.Then();
932 {
933 HValue* smi_value =
934 AddUncasted<HForceRepresentation>(value, Representation::Smi());
935 HValue* key = BuildPushElement(object, smi_value, FAST_HOLEY_SMI_ELEMENTS);
936 environment()->Push(key);
937 }
938 has_smi_elements.Else();
939 {
940 IfBuilder has_object_elements(this);
941 has_object_elements.If<HCompareNumericAndBranch>(
942 kind, Add<HConstant>(FAST_HOLEY_ELEMENTS), Token::LTE);
943 has_object_elements.Then();
944 {
945 HValue* key = BuildPushElement(object, value, FAST_HOLEY_ELEMENTS);
946 environment()->Push(key);
947 }
948 has_object_elements.Else();
949 {
950 IfBuilder has_double_elements(this);
951 has_double_elements.If<HCompareNumericAndBranch>(
952 kind, Add<HConstant>(FAST_HOLEY_DOUBLE_ELEMENTS), Token::LTE);
953 has_double_elements.Then();
954 {
955 HValue* double_value =
956 AddUncasted<HForceRepresentation>(value, Representation::Double());
957 HValue* key =
958 BuildPushElement(object, double_value, FAST_HOLEY_DOUBLE_ELEMENTS);
959 environment()->Push(key);
960 }
961 has_double_elements.ElseDeopt(Deoptimizer::kFastArrayPushFailed);
962 has_double_elements.End();
963 }
964 has_object_elements.End();
965 }
966 has_smi_elements.End();
967
968 HValue* key = environment()->Pop();
969 return AddUncasted<HAdd>(key, graph()->GetConstant1());
970 }
971
972 Handle<Code> FastArrayPushStub::GenerateCode() { return DoGenerateCode(this); }
783 973
784 template <> 974 template <>
785 HValue* CodeStubGraphBuilder<GrowArrayElementsStub>::BuildCodeStub() { 975 HValue* CodeStubGraphBuilder<GrowArrayElementsStub>::BuildCodeStub() {
786 ElementsKind kind = casted_stub()->elements_kind(); 976 ElementsKind kind = casted_stub()->elements_kind();
787 if (IsFastDoubleElementsKind(kind)) { 977 if (IsFastDoubleElementsKind(kind)) {
788 info()->MarkAsSavesCallerDoubles(); 978 info()->MarkAsSavesCallerDoubles();
789 } 979 }
790 980
791 HValue* object = GetParameter(GrowArrayElementsDescriptor::kObjectIndex); 981 HValue* object = GetParameter(GrowArrayElementsDescriptor::kObjectIndex);
792 HValue* key = GetParameter(GrowArrayElementsDescriptor::kKeyIndex); 982 HValue* key = GetParameter(GrowArrayElementsDescriptor::kKeyIndex);
(...skipping 1570 matching lines...) Expand 10 before | Expand all | Expand 10 after
2363 return Pop(); 2553 return Pop();
2364 } 2554 }
2365 2555
2366 2556
2367 Handle<Code> KeyedLoadGenericStub::GenerateCode() { 2557 Handle<Code> KeyedLoadGenericStub::GenerateCode() {
2368 return DoGenerateCode(this); 2558 return DoGenerateCode(this);
2369 } 2559 }
2370 2560
2371 } // namespace internal 2561 } // namespace internal
2372 } // namespace v8 2562 } // namespace v8
OLDNEW
« no previous file with comments | « src/code-stubs.h ('k') | src/crankshaft/arm/lithium-codegen-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698