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

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: Cleanup 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/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 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* bit = AddUncasted<HBitwise>(Token::BIT_AND, bit_field2, mask);
Jakob Kummerow 2016/03/21 15:12:51 nit: call it "bits", could be more than one.
828 IfBuilder check(this);
829 check.If<HCompareNumericAndBranch>(
830 bit, 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 properties on arrays. It's nonconfigurable, hence is
Jakob Kummerow 2016/03/21 15:12:51 nit: s/properties/property/
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 writable(this);
Jakob Kummerow 2016/03/21 15:12:51 nit: this should be called "readonly" (to make the
873 writable.If<HCompareNumericAndBranch>(bit, mask, Token::EQ);
874 writable.ThenDeopt(Deoptimizer::kFastArrayPushFailed);
875 writable.End();
876 }
877
878 environment()->Push(map);
879 LoopBuilder check_prototypes(this);
880 check_prototypes.BeginBody(1);
881 {
882 HValue* parent_map = environment()->Pop();
883 HValue* prototype = Add<HLoadNamedField>(parent_map, nullptr,
884 HObjectAccess::ForPrototype());
885
886 IfBuilder is_null(this);
887 is_null.If<HCompareObjectEqAndBranch>(prototype,
888 graph()->GetConstantNull());
889 is_null.Then();
890 check_prototypes.Break();
891 is_null.End();
892
893 HValue* prototype_map =
894 Add<HLoadNamedField>(prototype, nullptr, HObjectAccess::ForMap());
895 HValue* instance_type = Add<HLoadNamedField>(
896 prototype_map, nullptr, HObjectAccess::ForMapInstanceType());
897 IfBuilder check_instance_type(this);
898 check_instance_type.If<HCompareNumericAndBranch>(
899 instance_type, Add<HConstant>(JS_VALUE_TYPE), Token::LTE);
Jakob Kummerow 2016/03/21 15:12:51 This looks like a use case for the recently introd
900 check_instance_type.ThenDeopt(Deoptimizer::kFastArrayPushFailed);
901 check_instance_type.End();
902
903 HValue* elements = Add<HLoadNamedField>(
904 prototype, nullptr, HObjectAccess::ForElementsPointer());
905 IfBuilder no_elements(this);
906 no_elements.If<HCompareObjectEqAndBranch>(
907 elements, Add<HConstant>(isolate()->factory()->empty_fixed_array()));
908 no_elements.Then();
909 no_elements.ElseDeopt(Deoptimizer::kFastArrayPushFailed);
Jakob Kummerow 2016/03/21 15:12:51 nit: you could also use IfNot/ThenDeopt. Up to you
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());
Jakob Kummerow 2016/03/21 15:12:51 This is duplicated from line 823. Suggestion: hois
918 HValue* kind = BuildDecodeField<Map::ElementsKindBits>(bit_field2);
919
920 IfBuilder is_smi(this);
Jakob Kummerow 2016/03/21 15:12:51 nit: I'd prefer the name "has_smi_elements".
921 is_smi.If<HCompareNumericAndBranch>(
922 kind, Add<HConstant>(FAST_HOLEY_SMI_ELEMENTS), Token::LTE);
Jakob Kummerow 2016/03/21 15:12:51 nit: a comment and a check would be nice, roughly:
923 is_smi.Then();
924 {
925 HValue* smi_value =
926 AddUncasted<HForceRepresentation>(value, Representation::Smi());
927 HValue* key = BuildPushElement(object, smi_value, FAST_HOLEY_SMI_ELEMENTS);
928 environment()->Push(key);
929 }
930 is_smi.Else();
931 {
932 IfBuilder is_object(this);
Jakob Kummerow 2016/03/21 15:12:50 nit: has_object_elements
933 is_object.If<HCompareNumericAndBranch>(
934 kind, Add<HConstant>(FAST_HOLEY_ELEMENTS), Token::LTE);
935 is_object.Then();
936 {
937 HValue* key = BuildPushElement(object, value, FAST_HOLEY_ELEMENTS);
938 environment()->Push(key);
939 }
940 is_object.Else();
941 {
942 IfBuilder is_double(this);
943 is_double.If<HCompareNumericAndBranch>(
944 kind, Add<HConstant>(FAST_HOLEY_DOUBLE_ELEMENTS), Token::GT);
945 is_double.ThenDeopt(Deoptimizer::kFastArrayPushFailed);
946 is_double.End();
947
948 HValue* double_value =
949 AddUncasted<HForceRepresentation>(value, Representation::Double());
950 HValue* key =
951 BuildPushElement(object, double_value, FAST_HOLEY_DOUBLE_ELEMENTS);
952 environment()->Push(key);
953 }
954 is_object.End();
955 }
956 is_smi.End();
957
958 HValue* key = environment()->Pop();
959 return AddUncasted<HAdd>(key, graph()->GetConstant1());
960 }
961
962 Handle<Code> FastArrayPushStub::GenerateCode() { return DoGenerateCode(this); }
783 963
784 template <> 964 template <>
785 HValue* CodeStubGraphBuilder<GrowArrayElementsStub>::BuildCodeStub() { 965 HValue* CodeStubGraphBuilder<GrowArrayElementsStub>::BuildCodeStub() {
786 ElementsKind kind = casted_stub()->elements_kind(); 966 ElementsKind kind = casted_stub()->elements_kind();
787 if (IsFastDoubleElementsKind(kind)) { 967 if (IsFastDoubleElementsKind(kind)) {
788 info()->MarkAsSavesCallerDoubles(); 968 info()->MarkAsSavesCallerDoubles();
789 } 969 }
790 970
791 HValue* object = GetParameter(GrowArrayElementsDescriptor::kObjectIndex); 971 HValue* object = GetParameter(GrowArrayElementsDescriptor::kObjectIndex);
792 HValue* key = GetParameter(GrowArrayElementsDescriptor::kKeyIndex); 972 HValue* key = GetParameter(GrowArrayElementsDescriptor::kKeyIndex);
(...skipping 1571 matching lines...) Expand 10 before | Expand all | Expand 10 after
2364 return Pop(); 2544 return Pop();
2365 } 2545 }
2366 2546
2367 2547
2368 Handle<Code> KeyedLoadGenericStub::GenerateCode() { 2548 Handle<Code> KeyedLoadGenericStub::GenerateCode() {
2369 return DoGenerateCode(this); 2549 return DoGenerateCode(this);
2370 } 2550 }
2371 2551
2372 } // namespace internal 2552 } // namespace internal
2373 } // namespace v8 2553 } // 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