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 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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); | 81 HValue* BuildPushElement(HValue* object, HValue* argc, |
| 82 HValue* argument_elements, ElementsKind kind); |
82 | 83 |
83 enum ArgumentClass { | 84 enum ArgumentClass { |
84 NONE, | 85 NONE, |
85 SINGLE, | 86 SINGLE, |
86 MULTIPLE | 87 MULTIPLE |
87 }; | 88 }; |
88 | 89 |
89 HValue* UnmappedCase(HValue* elements, HValue* key, HValue* value); | 90 HValue* UnmappedCase(HValue* elements, HValue* key, HValue* value); |
90 HValue* EmitKeyedSloppyArguments(HValue* receiver, HValue* key, | 91 HValue* EmitKeyedSloppyArguments(HValue* receiver, HValue* key, |
91 HValue* value); | 92 HValue* value); |
(...skipping 683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
775 HObjectAccess::ForContextSlot(slot_index), | 776 HObjectAccess::ForContextSlot(slot_index), |
776 GetParameter(2), STORE_TO_INITIALIZED_ENTRY); | 777 GetParameter(2), STORE_TO_INITIALIZED_ENTRY); |
777 return GetParameter(2); | 778 return GetParameter(2); |
778 } | 779 } |
779 | 780 |
780 | 781 |
781 Handle<Code> StoreScriptContextFieldStub::GenerateCode() { | 782 Handle<Code> StoreScriptContextFieldStub::GenerateCode() { |
782 return DoGenerateCode(this); | 783 return DoGenerateCode(this); |
783 } | 784 } |
784 | 785 |
785 HValue* CodeStubGraphBuilderBase::BuildPushElement(HValue* object, | 786 HValue* CodeStubGraphBuilderBase::BuildPushElement(HValue* object, HValue* argc, |
786 HValue* value, | 787 HValue* argument_elements, |
787 ElementsKind kind) { | 788 ElementsKind kind) { |
| 789 // Precheck whether all elements fit into the array. |
| 790 if (!IsFastObjectElementsKind(kind)) { |
| 791 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); |
| 792 HValue* start = graph()->GetConstant0(); |
| 793 HValue* key = builder.BeginBody(start, argc, Token::LT); |
| 794 { |
| 795 HInstruction* argument = |
| 796 Add<HAccessArgumentsAt>(argument_elements, argc, key); |
| 797 Representation r = IsFastSmiElementsKind(kind) ? Representation::Smi() |
| 798 : Representation::Double(); |
| 799 AddUncasted<HForceRepresentation>(argument, r); |
| 800 } |
| 801 builder.EndBody(); |
| 802 } |
| 803 |
788 HValue* length = Add<HLoadNamedField>(object, nullptr, | 804 HValue* length = Add<HLoadNamedField>(object, nullptr, |
789 HObjectAccess::ForArrayLength(kind)); | 805 HObjectAccess::ForArrayLength(kind)); |
790 HValue* key = length; | 806 HValue* new_length = AddUncasted<HAdd>(length, argc); |
| 807 HValue* max_key = AddUncasted<HSub>(new_length, graph()->GetConstant1()); |
| 808 |
791 HValue* elements = Add<HLoadNamedField>(object, nullptr, | 809 HValue* elements = Add<HLoadNamedField>(object, nullptr, |
792 HObjectAccess::ForElementsPointer()); | 810 HObjectAccess::ForElementsPointer()); |
793 elements = BuildCheckForCapacityGrow(object, elements, kind, length, key, | 811 elements = BuildCheckForCapacityGrow(object, elements, kind, length, max_key, |
794 true, STORE); | 812 true, STORE); |
795 AddElementAccess(elements, key, value, object, nullptr, kind, STORE); | 813 |
796 return key; | 814 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); |
| 815 HValue* start = graph()->GetConstant0(); |
| 816 HValue* key = builder.BeginBody(start, argc, Token::LT); |
| 817 { |
| 818 HValue* argument = Add<HAccessArgumentsAt>(argument_elements, argc, key); |
| 819 HValue* index = AddUncasted<HAdd>(key, length); |
| 820 AddElementAccess(elements, index, argument, object, nullptr, kind, STORE); |
| 821 } |
| 822 builder.EndBody(); |
| 823 return new_length; |
797 } | 824 } |
798 | 825 |
799 template <> | 826 template <> |
800 HValue* CodeStubGraphBuilder<FastArrayPushStub>::BuildCodeStub() { | 827 HValue* CodeStubGraphBuilder<FastArrayPushStub>::BuildCodeStub() { |
801 // TODO(verwaest): Fix deoptimizer messages. | 828 // TODO(verwaest): Fix deoptimizer messages. |
802 HValue* argc = GetArgumentsLength(); | 829 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); | 830 HInstruction* argument_elements = Add<HArgumentsElements>(false, false); |
810 HInstruction* object = Add<HAccessArgumentsAt>(argument_elements, argc, | 831 HInstruction* object = Add<HAccessArgumentsAt>(argument_elements, argc, |
811 graph()->GetConstantMinus1()); | 832 graph()->GetConstantMinus1()); |
812 HInstruction* value = | |
813 Add<HAccessArgumentsAt>(argument_elements, argc, graph()->GetConstant0()); | |
814 | |
815 BuildCheckHeapObject(object); | 833 BuildCheckHeapObject(object); |
816 HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap()); | 834 HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap()); |
817 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_JS_ARRAY); | 835 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_JS_ARRAY); |
818 | 836 |
819 // Disallow pushing onto prototypes. It might be the JSArray prototype. | 837 // Disallow pushing onto prototypes. It might be the JSArray prototype. |
820 // Disallow pushing onto non-extensible objects. | 838 // Disallow pushing onto non-extensible objects. |
821 { | 839 { |
822 HValue* bit_field2 = | 840 HValue* bit_field2 = |
823 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2()); | 841 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2()); |
824 HValue* mask = | 842 HValue* mask = |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
923 STATIC_ASSERT(FAST_SMI_ELEMENTS < FAST_HOLEY_SMI_ELEMENTS); | 941 STATIC_ASSERT(FAST_SMI_ELEMENTS < FAST_HOLEY_SMI_ELEMENTS); |
924 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS < FAST_HOLEY_ELEMENTS); | 942 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS < FAST_HOLEY_ELEMENTS); |
925 STATIC_ASSERT(FAST_ELEMENTS < FAST_HOLEY_ELEMENTS); | 943 STATIC_ASSERT(FAST_ELEMENTS < FAST_HOLEY_ELEMENTS); |
926 STATIC_ASSERT(FAST_HOLEY_ELEMENTS < FAST_HOLEY_DOUBLE_ELEMENTS); | 944 STATIC_ASSERT(FAST_HOLEY_ELEMENTS < FAST_HOLEY_DOUBLE_ELEMENTS); |
927 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FAST_HOLEY_DOUBLE_ELEMENTS); | 945 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FAST_HOLEY_DOUBLE_ELEMENTS); |
928 IfBuilder has_smi_elements(this); | 946 IfBuilder has_smi_elements(this); |
929 has_smi_elements.If<HCompareNumericAndBranch>( | 947 has_smi_elements.If<HCompareNumericAndBranch>( |
930 kind, Add<HConstant>(FAST_HOLEY_SMI_ELEMENTS), Token::LTE); | 948 kind, Add<HConstant>(FAST_HOLEY_SMI_ELEMENTS), Token::LTE); |
931 has_smi_elements.Then(); | 949 has_smi_elements.Then(); |
932 { | 950 { |
933 HValue* smi_value = | 951 HValue* new_length = BuildPushElement(object, argc, argument_elements, |
934 AddUncasted<HForceRepresentation>(value, Representation::Smi()); | 952 FAST_HOLEY_SMI_ELEMENTS); |
935 HValue* key = BuildPushElement(object, smi_value, FAST_HOLEY_SMI_ELEMENTS); | 953 environment()->Push(new_length); |
936 environment()->Push(key); | |
937 } | 954 } |
938 has_smi_elements.Else(); | 955 has_smi_elements.Else(); |
939 { | 956 { |
940 IfBuilder has_object_elements(this); | 957 IfBuilder has_object_elements(this); |
941 has_object_elements.If<HCompareNumericAndBranch>( | 958 has_object_elements.If<HCompareNumericAndBranch>( |
942 kind, Add<HConstant>(FAST_HOLEY_ELEMENTS), Token::LTE); | 959 kind, Add<HConstant>(FAST_HOLEY_ELEMENTS), Token::LTE); |
943 has_object_elements.Then(); | 960 has_object_elements.Then(); |
944 { | 961 { |
945 HValue* key = BuildPushElement(object, value, FAST_HOLEY_ELEMENTS); | 962 HValue* new_length = BuildPushElement(object, argc, argument_elements, |
946 environment()->Push(key); | 963 FAST_HOLEY_ELEMENTS); |
| 964 environment()->Push(new_length); |
947 } | 965 } |
948 has_object_elements.Else(); | 966 has_object_elements.Else(); |
949 { | 967 { |
950 IfBuilder has_double_elements(this); | 968 IfBuilder has_double_elements(this); |
951 has_double_elements.If<HCompareNumericAndBranch>( | 969 has_double_elements.If<HCompareNumericAndBranch>( |
952 kind, Add<HConstant>(FAST_HOLEY_DOUBLE_ELEMENTS), Token::LTE); | 970 kind, Add<HConstant>(FAST_HOLEY_DOUBLE_ELEMENTS), Token::LTE); |
953 has_double_elements.Then(); | 971 has_double_elements.Then(); |
954 { | 972 { |
955 HValue* double_value = | 973 HValue* new_length = BuildPushElement(object, argc, argument_elements, |
956 AddUncasted<HForceRepresentation>(value, Representation::Double()); | 974 FAST_HOLEY_DOUBLE_ELEMENTS); |
957 HValue* key = | 975 environment()->Push(new_length); |
958 BuildPushElement(object, double_value, FAST_HOLEY_DOUBLE_ELEMENTS); | |
959 environment()->Push(key); | |
960 } | 976 } |
961 has_double_elements.ElseDeopt(Deoptimizer::kFastArrayPushFailed); | 977 has_double_elements.ElseDeopt(Deoptimizer::kFastArrayPushFailed); |
962 has_double_elements.End(); | 978 has_double_elements.End(); |
963 } | 979 } |
964 has_object_elements.End(); | 980 has_object_elements.End(); |
965 } | 981 } |
966 has_smi_elements.End(); | 982 has_smi_elements.End(); |
967 | 983 |
968 HValue* key = environment()->Pop(); | 984 return environment()->Pop(); |
969 return AddUncasted<HAdd>(key, graph()->GetConstant1()); | |
970 } | 985 } |
971 | 986 |
972 Handle<Code> FastArrayPushStub::GenerateCode() { return DoGenerateCode(this); } | 987 Handle<Code> FastArrayPushStub::GenerateCode() { return DoGenerateCode(this); } |
973 | 988 |
974 template <> | 989 template <> |
975 HValue* CodeStubGraphBuilder<GrowArrayElementsStub>::BuildCodeStub() { | 990 HValue* CodeStubGraphBuilder<GrowArrayElementsStub>::BuildCodeStub() { |
976 ElementsKind kind = casted_stub()->elements_kind(); | 991 ElementsKind kind = casted_stub()->elements_kind(); |
977 if (IsFastDoubleElementsKind(kind)) { | 992 if (IsFastDoubleElementsKind(kind)) { |
978 info()->MarkAsSavesCallerDoubles(); | 993 info()->MarkAsSavesCallerDoubles(); |
979 } | 994 } |
(...skipping 1573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2553 return Pop(); | 2568 return Pop(); |
2554 } | 2569 } |
2555 | 2570 |
2556 | 2571 |
2557 Handle<Code> KeyedLoadGenericStub::GenerateCode() { | 2572 Handle<Code> KeyedLoadGenericStub::GenerateCode() { |
2558 return DoGenerateCode(this); | 2573 return DoGenerateCode(this); |
2559 } | 2574 } |
2560 | 2575 |
2561 } // namespace internal | 2576 } // namespace internal |
2562 } // namespace v8 | 2577 } // namespace v8 |
OLD | NEW |