| 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 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 UNIMPLEMENTED(); | 200 UNIMPLEMENTED(); |
| 201 return NULL; | 201 return NULL; |
| 202 } | 202 } |
| 203 | 203 |
| 204 virtual HValue* BuildCodeUninitializedStub() { | 204 virtual HValue* BuildCodeUninitializedStub() { |
| 205 // Force a deopt that falls back to the runtime. | 205 // Force a deopt that falls back to the runtime. |
| 206 HValue* undefined = graph()->GetConstantUndefined(); | 206 HValue* undefined = graph()->GetConstantUndefined(); |
| 207 IfBuilder builder(this); | 207 IfBuilder builder(this); |
| 208 builder.IfNot<HCompareObjectEqAndBranch, HValue*>(undefined, undefined); | 208 builder.IfNot<HCompareObjectEqAndBranch, HValue*>(undefined, undefined); |
| 209 builder.Then(); | 209 builder.Then(); |
| 210 builder.ElseDeopt(Deoptimizer::kForcedDeoptToRuntime); | 210 builder.ElseDeopt(DeoptimizeReason::kForcedDeoptToRuntime); |
| 211 return undefined; | 211 return undefined; |
| 212 } | 212 } |
| 213 | 213 |
| 214 Stub* casted_stub() { return static_cast<Stub*>(stub()); } | 214 Stub* casted_stub() { return static_cast<Stub*>(stub()); } |
| 215 }; | 215 }; |
| 216 | 216 |
| 217 | 217 |
| 218 Handle<Code> HydrogenCodeStub::GenerateLightweightMissCode( | 218 Handle<Code> HydrogenCodeStub::GenerateLightweightMissCode( |
| 219 ExternalReference miss) { | 219 ExternalReference miss) { |
| 220 Factory* factory = isolate()->factory(); | 220 Factory* factory = isolate()->factory(); |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 440 Add<HLoadNamedField>(boilerplate, nullptr, | 440 Add<HLoadNamedField>(boilerplate, nullptr, |
| 441 HObjectAccess::ForElementsPointer())); | 441 HObjectAccess::ForElementsPointer())); |
| 442 for (int offset = JSObject::kHeaderSize; offset < result_size; | 442 for (int offset = JSObject::kHeaderSize; offset < result_size; |
| 443 offset += kPointerSize) { | 443 offset += kPointerSize) { |
| 444 HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(offset); | 444 HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(offset); |
| 445 Add<HStoreNamedField>(result, access, | 445 Add<HStoreNamedField>(result, access, |
| 446 Add<HLoadNamedField>(boilerplate, nullptr, access)); | 446 Add<HLoadNamedField>(boilerplate, nullptr, access)); |
| 447 } | 447 } |
| 448 Push(result); | 448 Push(result); |
| 449 } | 449 } |
| 450 if_notundefined.ElseDeopt(Deoptimizer::kUninitializedBoilerplateInFastClone); | 450 if_notundefined.ElseDeopt( |
| 451 DeoptimizeReason::kUninitializedBoilerplateInFastClone); |
| 451 if_notundefined.End(); | 452 if_notundefined.End(); |
| 452 | 453 |
| 453 return Pop(); | 454 return Pop(); |
| 454 } | 455 } |
| 455 | 456 |
| 456 | 457 |
| 457 Handle<Code> FastCloneRegExpStub::GenerateCode() { | 458 Handle<Code> FastCloneRegExpStub::GenerateCode() { |
| 458 return DoGenerateCode(this); | 459 return DoGenerateCode(this); |
| 459 } | 460 } |
| 460 | 461 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 | 520 |
| 520 if_fixed.Else(); | 521 if_fixed.Else(); |
| 521 Push(BuildCloneShallowArrayNonEmpty(boilerplate, | 522 Push(BuildCloneShallowArrayNonEmpty(boilerplate, |
| 522 allocation_site, | 523 allocation_site, |
| 523 alloc_site_mode, | 524 alloc_site_mode, |
| 524 FAST_DOUBLE_ELEMENTS)); | 525 FAST_DOUBLE_ELEMENTS)); |
| 525 if_fixed.End(); | 526 if_fixed.End(); |
| 526 if_fixed_cow.End(); | 527 if_fixed_cow.End(); |
| 527 zero_capacity.End(); | 528 zero_capacity.End(); |
| 528 | 529 |
| 529 checker.ElseDeopt(Deoptimizer::kUninitializedBoilerplateLiterals); | 530 checker.ElseDeopt(DeoptimizeReason::kUninitializedBoilerplateLiterals); |
| 530 checker.End(); | 531 checker.End(); |
| 531 | 532 |
| 532 return environment()->Pop(); | 533 return environment()->Pop(); |
| 533 } | 534 } |
| 534 | 535 |
| 535 | 536 |
| 536 Handle<Code> FastCloneShallowArrayStub::GenerateCode() { | 537 Handle<Code> FastCloneShallowArrayStub::GenerateCode() { |
| 537 return DoGenerateCode(this); | 538 return DoGenerateCode(this); |
| 538 } | 539 } |
| 539 | 540 |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 692 { | 693 { |
| 693 HInstruction* argument = | 694 HInstruction* argument = |
| 694 Add<HAccessArgumentsAt>(argument_elements, argc, key); | 695 Add<HAccessArgumentsAt>(argument_elements, argc, key); |
| 695 IfBuilder can_store(this); | 696 IfBuilder can_store(this); |
| 696 can_store.IfNot<HIsSmiAndBranch>(argument); | 697 can_store.IfNot<HIsSmiAndBranch>(argument); |
| 697 if (IsFastDoubleElementsKind(kind)) { | 698 if (IsFastDoubleElementsKind(kind)) { |
| 698 can_store.And(); | 699 can_store.And(); |
| 699 can_store.IfNot<HCompareMap>(argument, | 700 can_store.IfNot<HCompareMap>(argument, |
| 700 isolate()->factory()->heap_number_map()); | 701 isolate()->factory()->heap_number_map()); |
| 701 } | 702 } |
| 702 can_store.ThenDeopt(Deoptimizer::kFastPathFailed); | 703 can_store.ThenDeopt(DeoptimizeReason::kFastPathFailed); |
| 703 can_store.End(); | 704 can_store.End(); |
| 704 } | 705 } |
| 705 builder.EndBody(); | 706 builder.EndBody(); |
| 706 } | 707 } |
| 707 | 708 |
| 708 HValue* length = Add<HLoadNamedField>(object, nullptr, | 709 HValue* length = Add<HLoadNamedField>(object, nullptr, |
| 709 HObjectAccess::ForArrayLength(kind)); | 710 HObjectAccess::ForArrayLength(kind)); |
| 710 HValue* new_length = AddUncasted<HAdd>(length, argc); | 711 HValue* new_length = AddUncasted<HAdd>(length, argc); |
| 711 HValue* max_key = AddUncasted<HSub>(new_length, graph()->GetConstant1()); | 712 HValue* max_key = AddUncasted<HSub>(new_length, graph()->GetConstant1()); |
| 712 | 713 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 743 { | 744 { |
| 744 HValue* bit_field2 = | 745 HValue* bit_field2 = |
| 745 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2()); | 746 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2()); |
| 746 HValue* mask = | 747 HValue* mask = |
| 747 Add<HConstant>(static_cast<int>(Map::IsPrototypeMapBits::kMask) | | 748 Add<HConstant>(static_cast<int>(Map::IsPrototypeMapBits::kMask) | |
| 748 (1 << Map::kIsExtensible)); | 749 (1 << Map::kIsExtensible)); |
| 749 HValue* bits = AddUncasted<HBitwise>(Token::BIT_AND, bit_field2, mask); | 750 HValue* bits = AddUncasted<HBitwise>(Token::BIT_AND, bit_field2, mask); |
| 750 IfBuilder check(this); | 751 IfBuilder check(this); |
| 751 check.If<HCompareNumericAndBranch>( | 752 check.If<HCompareNumericAndBranch>( |
| 752 bits, Add<HConstant>(1 << Map::kIsExtensible), Token::NE); | 753 bits, Add<HConstant>(1 << Map::kIsExtensible), Token::NE); |
| 753 check.ThenDeopt(Deoptimizer::kFastPathFailed); | 754 check.ThenDeopt(DeoptimizeReason::kFastPathFailed); |
| 754 check.End(); | 755 check.End(); |
| 755 } | 756 } |
| 756 | 757 |
| 757 // Disallow pushing onto arrays in dictionary named property mode. We need to | 758 // Disallow pushing onto arrays in dictionary named property mode. We need to |
| 758 // figure out whether the length property is still writable. | 759 // figure out whether the length property is still writable. |
| 759 { | 760 { |
| 760 HValue* bit_field3 = | 761 HValue* bit_field3 = |
| 761 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField3()); | 762 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField3()); |
| 762 HValue* mask = Add<HConstant>(static_cast<int>(Map::DictionaryMap::kMask)); | 763 HValue* mask = Add<HConstant>(static_cast<int>(Map::DictionaryMap::kMask)); |
| 763 HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, bit_field3, mask); | 764 HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, bit_field3, mask); |
| 764 IfBuilder check(this); | 765 IfBuilder check(this); |
| 765 check.If<HCompareNumericAndBranch>(bit, mask, Token::EQ); | 766 check.If<HCompareNumericAndBranch>(bit, mask, Token::EQ); |
| 766 check.ThenDeopt(Deoptimizer::kFastPathFailed); | 767 check.ThenDeopt(DeoptimizeReason::kFastPathFailed); |
| 767 check.End(); | 768 check.End(); |
| 768 } | 769 } |
| 769 | 770 |
| 770 // Check whether the length property is writable. The length property is the | 771 // Check whether the length property is writable. The length property is the |
| 771 // only default named property on arrays. It's nonconfigurable, hence is | 772 // only default named property on arrays. It's nonconfigurable, hence is |
| 772 // guaranteed to stay the first property. | 773 // guaranteed to stay the first property. |
| 773 { | 774 { |
| 774 HValue* descriptors = | 775 HValue* descriptors = |
| 775 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapDescriptors()); | 776 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapDescriptors()); |
| 776 HValue* details = Add<HLoadKeyed>( | 777 HValue* details = Add<HLoadKeyed>( |
| 777 descriptors, Add<HConstant>(DescriptorArray::ToDetailsIndex(0)), | 778 descriptors, Add<HConstant>(DescriptorArray::ToDetailsIndex(0)), |
| 778 nullptr, nullptr, FAST_SMI_ELEMENTS); | 779 nullptr, nullptr, FAST_SMI_ELEMENTS); |
| 779 HValue* mask = | 780 HValue* mask = |
| 780 Add<HConstant>(READ_ONLY << PropertyDetails::AttributesField::kShift); | 781 Add<HConstant>(READ_ONLY << PropertyDetails::AttributesField::kShift); |
| 781 HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, details, mask); | 782 HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, details, mask); |
| 782 IfBuilder readonly(this); | 783 IfBuilder readonly(this); |
| 783 readonly.If<HCompareNumericAndBranch>(bit, mask, Token::EQ); | 784 readonly.If<HCompareNumericAndBranch>(bit, mask, Token::EQ); |
| 784 readonly.ThenDeopt(Deoptimizer::kFastPathFailed); | 785 readonly.ThenDeopt(DeoptimizeReason::kFastPathFailed); |
| 785 readonly.End(); | 786 readonly.End(); |
| 786 } | 787 } |
| 787 | 788 |
| 788 HValue* null = Add<HLoadRoot>(Heap::kNullValueRootIndex); | 789 HValue* null = Add<HLoadRoot>(Heap::kNullValueRootIndex); |
| 789 HValue* empty = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex); | 790 HValue* empty = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex); |
| 790 environment()->Push(map); | 791 environment()->Push(map); |
| 791 LoopBuilder check_prototypes(this); | 792 LoopBuilder check_prototypes(this); |
| 792 check_prototypes.BeginBody(1); | 793 check_prototypes.BeginBody(1); |
| 793 { | 794 { |
| 794 HValue* parent_map = environment()->Pop(); | 795 HValue* parent_map = environment()->Pop(); |
| 795 HValue* prototype = Add<HLoadNamedField>(parent_map, nullptr, | 796 HValue* prototype = Add<HLoadNamedField>(parent_map, nullptr, |
| 796 HObjectAccess::ForPrototype()); | 797 HObjectAccess::ForPrototype()); |
| 797 | 798 |
| 798 IfBuilder is_null(this); | 799 IfBuilder is_null(this); |
| 799 is_null.If<HCompareObjectEqAndBranch>(prototype, null); | 800 is_null.If<HCompareObjectEqAndBranch>(prototype, null); |
| 800 is_null.Then(); | 801 is_null.Then(); |
| 801 check_prototypes.Break(); | 802 check_prototypes.Break(); |
| 802 is_null.End(); | 803 is_null.End(); |
| 803 | 804 |
| 804 HValue* prototype_map = | 805 HValue* prototype_map = |
| 805 Add<HLoadNamedField>(prototype, nullptr, HObjectAccess::ForMap()); | 806 Add<HLoadNamedField>(prototype, nullptr, HObjectAccess::ForMap()); |
| 806 HValue* instance_type = Add<HLoadNamedField>( | 807 HValue* instance_type = Add<HLoadNamedField>( |
| 807 prototype_map, nullptr, HObjectAccess::ForMapInstanceType()); | 808 prototype_map, nullptr, HObjectAccess::ForMapInstanceType()); |
| 808 IfBuilder check_instance_type(this); | 809 IfBuilder check_instance_type(this); |
| 809 check_instance_type.If<HCompareNumericAndBranch>( | 810 check_instance_type.If<HCompareNumericAndBranch>( |
| 810 instance_type, Add<HConstant>(LAST_CUSTOM_ELEMENTS_RECEIVER), | 811 instance_type, Add<HConstant>(LAST_CUSTOM_ELEMENTS_RECEIVER), |
| 811 Token::LTE); | 812 Token::LTE); |
| 812 check_instance_type.ThenDeopt(Deoptimizer::kFastPathFailed); | 813 check_instance_type.ThenDeopt(DeoptimizeReason::kFastPathFailed); |
| 813 check_instance_type.End(); | 814 check_instance_type.End(); |
| 814 | 815 |
| 815 HValue* elements = Add<HLoadNamedField>( | 816 HValue* elements = Add<HLoadNamedField>( |
| 816 prototype, nullptr, HObjectAccess::ForElementsPointer()); | 817 prototype, nullptr, HObjectAccess::ForElementsPointer()); |
| 817 IfBuilder no_elements(this); | 818 IfBuilder no_elements(this); |
| 818 no_elements.IfNot<HCompareObjectEqAndBranch>(elements, empty); | 819 no_elements.IfNot<HCompareObjectEqAndBranch>(elements, empty); |
| 819 no_elements.ThenDeopt(Deoptimizer::kFastPathFailed); | 820 no_elements.ThenDeopt(DeoptimizeReason::kFastPathFailed); |
| 820 no_elements.End(); | 821 no_elements.End(); |
| 821 | 822 |
| 822 environment()->Push(prototype_map); | 823 environment()->Push(prototype_map); |
| 823 } | 824 } |
| 824 check_prototypes.EndBody(); | 825 check_prototypes.EndBody(); |
| 825 | 826 |
| 826 HValue* bit_field2 = | 827 HValue* bit_field2 = |
| 827 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2()); | 828 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2()); |
| 828 HValue* kind = BuildDecodeField<Map::ElementsKindBits>(bit_field2); | 829 HValue* kind = BuildDecodeField<Map::ElementsKindBits>(bit_field2); |
| 829 | 830 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 859 { | 860 { |
| 860 IfBuilder has_double_elements(this); | 861 IfBuilder has_double_elements(this); |
| 861 has_double_elements.If<HCompareNumericAndBranch>( | 862 has_double_elements.If<HCompareNumericAndBranch>( |
| 862 kind, Add<HConstant>(FAST_HOLEY_DOUBLE_ELEMENTS), Token::LTE); | 863 kind, Add<HConstant>(FAST_HOLEY_DOUBLE_ELEMENTS), Token::LTE); |
| 863 has_double_elements.Then(); | 864 has_double_elements.Then(); |
| 864 { | 865 { |
| 865 HValue* new_length = BuildPushElement(object, argc, argument_elements, | 866 HValue* new_length = BuildPushElement(object, argc, argument_elements, |
| 866 FAST_HOLEY_DOUBLE_ELEMENTS); | 867 FAST_HOLEY_DOUBLE_ELEMENTS); |
| 867 environment()->Push(new_length); | 868 environment()->Push(new_length); |
| 868 } | 869 } |
| 869 has_double_elements.ElseDeopt(Deoptimizer::kFastPathFailed); | 870 has_double_elements.ElseDeopt(DeoptimizeReason::kFastPathFailed); |
| 870 has_double_elements.End(); | 871 has_double_elements.End(); |
| 871 } | 872 } |
| 872 has_object_elements.End(); | 873 has_object_elements.End(); |
| 873 } | 874 } |
| 874 has_smi_elements.End(); | 875 has_smi_elements.End(); |
| 875 | 876 |
| 876 return environment()->Pop(); | 877 return environment()->Pop(); |
| 877 } | 878 } |
| 878 | 879 |
| 879 Handle<Code> FastArrayPushStub::GenerateCode() { return DoGenerateCode(this); } | 880 Handle<Code> FastArrayPushStub::GenerateCode() { return DoGenerateCode(this); } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 891 | 892 |
| 892 // Disallow binding of slow-mode functions. We need to figure out whether the | 893 // Disallow binding of slow-mode functions. We need to figure out whether the |
| 893 // length and name property are in the original state. | 894 // length and name property are in the original state. |
| 894 { | 895 { |
| 895 HValue* bit_field3 = | 896 HValue* bit_field3 = |
| 896 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField3()); | 897 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField3()); |
| 897 HValue* mask = Add<HConstant>(static_cast<int>(Map::DictionaryMap::kMask)); | 898 HValue* mask = Add<HConstant>(static_cast<int>(Map::DictionaryMap::kMask)); |
| 898 HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, bit_field3, mask); | 899 HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, bit_field3, mask); |
| 899 IfBuilder check(this); | 900 IfBuilder check(this); |
| 900 check.If<HCompareNumericAndBranch>(bit, mask, Token::EQ); | 901 check.If<HCompareNumericAndBranch>(bit, mask, Token::EQ); |
| 901 check.ThenDeopt(Deoptimizer::kFastPathFailed); | 902 check.ThenDeopt(DeoptimizeReason::kFastPathFailed); |
| 902 check.End(); | 903 check.End(); |
| 903 } | 904 } |
| 904 | 905 |
| 905 // Check whether the length and name properties are still present as | 906 // Check whether the length and name properties are still present as |
| 906 // AccessorInfo objects. In that case, their value can be recomputed even if | 907 // AccessorInfo objects. In that case, their value can be recomputed even if |
| 907 // the actual value on the object changes. | 908 // the actual value on the object changes. |
| 908 { | 909 { |
| 909 HValue* descriptors = | 910 HValue* descriptors = |
| 910 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapDescriptors()); | 911 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapDescriptors()); |
| 911 | 912 |
| 912 HValue* descriptors_length = Add<HLoadNamedField>( | 913 HValue* descriptors_length = Add<HLoadNamedField>( |
| 913 descriptors, nullptr, HObjectAccess::ForFixedArrayLength()); | 914 descriptors, nullptr, HObjectAccess::ForFixedArrayLength()); |
| 914 IfBuilder range(this); | 915 IfBuilder range(this); |
| 915 range.If<HCompareNumericAndBranch>(descriptors_length, | 916 range.If<HCompareNumericAndBranch>(descriptors_length, |
| 916 graph()->GetConstant1(), Token::LTE); | 917 graph()->GetConstant1(), Token::LTE); |
| 917 range.ThenDeopt(Deoptimizer::kFastPathFailed); | 918 range.ThenDeopt(DeoptimizeReason::kFastPathFailed); |
| 918 range.End(); | 919 range.End(); |
| 919 | 920 |
| 920 // Verify .length. | 921 // Verify .length. |
| 921 const int length_index = JSFunction::kLengthDescriptorIndex; | 922 const int length_index = JSFunction::kLengthDescriptorIndex; |
| 922 HValue* maybe_length = Add<HLoadKeyed>( | 923 HValue* maybe_length = Add<HLoadKeyed>( |
| 923 descriptors, Add<HConstant>(DescriptorArray::ToKeyIndex(length_index)), | 924 descriptors, Add<HConstant>(DescriptorArray::ToKeyIndex(length_index)), |
| 924 nullptr, nullptr, FAST_ELEMENTS); | 925 nullptr, nullptr, FAST_ELEMENTS); |
| 925 Unique<Name> length_string = Unique<Name>::CreateUninitialized( | 926 Unique<Name> length_string = Unique<Name>::CreateUninitialized( |
| 926 isolate()->factory()->length_string()); | 927 isolate()->factory()->length_string()); |
| 927 Add<HCheckValue>(maybe_length, length_string, false); | 928 Add<HCheckValue>(maybe_length, length_string, false); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 984 | 985 |
| 985 // Verify that __proto__ matches that of a the target bound function. | 986 // Verify that __proto__ matches that of a the target bound function. |
| 986 { | 987 { |
| 987 HValue* prototype = | 988 HValue* prototype = |
| 988 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForPrototype()); | 989 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForPrototype()); |
| 989 HValue* expected_prototype = Add<HLoadNamedField>( | 990 HValue* expected_prototype = Add<HLoadNamedField>( |
| 990 bound_function_map, nullptr, HObjectAccess::ForPrototype()); | 991 bound_function_map, nullptr, HObjectAccess::ForPrototype()); |
| 991 IfBuilder equal_prototype(this); | 992 IfBuilder equal_prototype(this); |
| 992 equal_prototype.IfNot<HCompareObjectEqAndBranch>(prototype, | 993 equal_prototype.IfNot<HCompareObjectEqAndBranch>(prototype, |
| 993 expected_prototype); | 994 expected_prototype); |
| 994 equal_prototype.ThenDeopt(Deoptimizer::kFastPathFailed); | 995 equal_prototype.ThenDeopt(DeoptimizeReason::kFastPathFailed); |
| 995 equal_prototype.End(); | 996 equal_prototype.End(); |
| 996 } | 997 } |
| 997 | 998 |
| 998 // Allocate the arguments array. | 999 // Allocate the arguments array. |
| 999 IfBuilder empty_args(this); | 1000 IfBuilder empty_args(this); |
| 1000 empty_args.If<HCompareNumericAndBranch>(argc, graph()->GetConstant1(), | 1001 empty_args.If<HCompareNumericAndBranch>(argc, graph()->GetConstant1(), |
| 1001 Token::LTE); | 1002 Token::LTE); |
| 1002 empty_args.Then(); | 1003 empty_args.Then(); |
| 1003 { environment()->Push(Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex)); } | 1004 { environment()->Push(Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex)); } |
| 1004 empty_args.Else(); | 1005 empty_args.Else(); |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1174 Token::LT); | 1175 Token::LT); |
| 1175 in_unmapped_range.Then(); | 1176 in_unmapped_range.Then(); |
| 1176 { | 1177 { |
| 1177 if (value == NULL) { | 1178 if (value == NULL) { |
| 1178 result = Add<HLoadKeyed>(backing_store, key, nullptr, nullptr, | 1179 result = Add<HLoadKeyed>(backing_store, key, nullptr, nullptr, |
| 1179 FAST_HOLEY_ELEMENTS, NEVER_RETURN_HOLE); | 1180 FAST_HOLEY_ELEMENTS, NEVER_RETURN_HOLE); |
| 1180 } else { | 1181 } else { |
| 1181 Add<HStoreKeyed>(backing_store, key, value, nullptr, FAST_HOLEY_ELEMENTS); | 1182 Add<HStoreKeyed>(backing_store, key, value, nullptr, FAST_HOLEY_ELEMENTS); |
| 1182 } | 1183 } |
| 1183 } | 1184 } |
| 1184 in_unmapped_range.ElseDeopt(Deoptimizer::kOutsideOfRange); | 1185 in_unmapped_range.ElseDeopt(DeoptimizeReason::kOutsideOfRange); |
| 1185 in_unmapped_range.End(); | 1186 in_unmapped_range.End(); |
| 1186 return result; | 1187 return result; |
| 1187 } | 1188 } |
| 1188 | 1189 |
| 1189 | 1190 |
| 1190 HValue* CodeStubGraphBuilderBase::EmitKeyedSloppyArguments(HValue* receiver, | 1191 HValue* CodeStubGraphBuilderBase::EmitKeyedSloppyArguments(HValue* receiver, |
| 1191 HValue* key, | 1192 HValue* key, |
| 1192 HValue* value) { | 1193 HValue* value) { |
| 1193 // Mapped arguments are actual arguments. Unmapped arguments are values added | 1194 // Mapped arguments are actual arguments. Unmapped arguments are values added |
| 1194 // to the arguments object after it was created for the call. Mapped arguments | 1195 // to the arguments object after it was created for the call. Mapped arguments |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1215 // in the unmapped arguments array, as described above. Otherwise, t is a Smi | 1216 // in the unmapped arguments array, as described above. Otherwise, t is a Smi |
| 1216 // index into the context array given at elements[0]. Return the value at | 1217 // index into the context array given at elements[0]. Return the value at |
| 1217 // context[t]. | 1218 // context[t]. |
| 1218 | 1219 |
| 1219 bool is_load = value == NULL; | 1220 bool is_load = value == NULL; |
| 1220 | 1221 |
| 1221 key = AddUncasted<HForceRepresentation>(key, Representation::Smi()); | 1222 key = AddUncasted<HForceRepresentation>(key, Representation::Smi()); |
| 1222 IfBuilder positive_smi(this); | 1223 IfBuilder positive_smi(this); |
| 1223 positive_smi.If<HCompareNumericAndBranch>(key, graph()->GetConstant0(), | 1224 positive_smi.If<HCompareNumericAndBranch>(key, graph()->GetConstant0(), |
| 1224 Token::LT); | 1225 Token::LT); |
| 1225 positive_smi.ThenDeopt(Deoptimizer::kKeyIsNegative); | 1226 positive_smi.ThenDeopt(DeoptimizeReason::kKeyIsNegative); |
| 1226 positive_smi.End(); | 1227 positive_smi.End(); |
| 1227 | 1228 |
| 1228 HValue* constant_two = Add<HConstant>(2); | 1229 HValue* constant_two = Add<HConstant>(2); |
| 1229 HValue* elements = AddLoadElements(receiver, nullptr); | 1230 HValue* elements = AddLoadElements(receiver, nullptr); |
| 1230 HValue* elements_length = Add<HLoadNamedField>( | 1231 HValue* elements_length = Add<HLoadNamedField>( |
| 1231 elements, nullptr, HObjectAccess::ForFixedArrayLength()); | 1232 elements, nullptr, HObjectAccess::ForFixedArrayLength()); |
| 1232 HValue* adjusted_length = AddUncasted<HSub>(elements_length, constant_two); | 1233 HValue* adjusted_length = AddUncasted<HSub>(elements_length, constant_two); |
| 1233 IfBuilder in_range(this); | 1234 IfBuilder in_range(this); |
| 1234 in_range.If<HCompareNumericAndBranch>(key, adjusted_length, Token::LT); | 1235 in_range.If<HCompareNumericAndBranch>(key, adjusted_length, Token::LT); |
| 1235 in_range.Then(); | 1236 in_range.Then(); |
| (...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1800 HValue* global = | 1801 HValue* global = |
| 1801 Add<HLoadNamedField>(proxy_map, nullptr, HObjectAccess::ForPrototype()); | 1802 Add<HLoadNamedField>(proxy_map, nullptr, HObjectAccess::ForPrototype()); |
| 1802 HValue* map_cell = Add<HConstant>(isolate()->factory()->NewWeakCell( | 1803 HValue* map_cell = Add<HConstant>(isolate()->factory()->NewWeakCell( |
| 1803 StoreGlobalStub::global_map_placeholder(isolate()))); | 1804 StoreGlobalStub::global_map_placeholder(isolate()))); |
| 1804 HValue* expected_map = Add<HLoadNamedField>( | 1805 HValue* expected_map = Add<HLoadNamedField>( |
| 1805 map_cell, nullptr, HObjectAccess::ForWeakCellValue()); | 1806 map_cell, nullptr, HObjectAccess::ForWeakCellValue()); |
| 1806 HValue* map = | 1807 HValue* map = |
| 1807 Add<HLoadNamedField>(global, nullptr, HObjectAccess::ForMap()); | 1808 Add<HLoadNamedField>(global, nullptr, HObjectAccess::ForMap()); |
| 1808 IfBuilder map_check(this); | 1809 IfBuilder map_check(this); |
| 1809 map_check.IfNot<HCompareObjectEqAndBranch>(expected_map, map); | 1810 map_check.IfNot<HCompareObjectEqAndBranch>(expected_map, map); |
| 1810 map_check.ThenDeopt(Deoptimizer::kUnknownMap); | 1811 map_check.ThenDeopt(DeoptimizeReason::kUnknownMap); |
| 1811 map_check.End(); | 1812 map_check.End(); |
| 1812 } | 1813 } |
| 1813 | 1814 |
| 1814 HValue* weak_cell = Add<HConstant>(isolate()->factory()->NewWeakCell( | 1815 HValue* weak_cell = Add<HConstant>(isolate()->factory()->NewWeakCell( |
| 1815 StoreGlobalStub::property_cell_placeholder(isolate()))); | 1816 StoreGlobalStub::property_cell_placeholder(isolate()))); |
| 1816 HValue* cell = Add<HLoadNamedField>(weak_cell, nullptr, | 1817 HValue* cell = Add<HLoadNamedField>(weak_cell, nullptr, |
| 1817 HObjectAccess::ForWeakCellValue()); | 1818 HObjectAccess::ForWeakCellValue()); |
| 1818 Add<HCheckHeapObject>(cell); | 1819 Add<HCheckHeapObject>(cell); |
| 1819 HObjectAccess access = HObjectAccess::ForPropertyCellValue(); | 1820 HObjectAccess access = HObjectAccess::ForPropertyCellValue(); |
| 1820 // Load the payload of the global parameter cell. A hole indicates that the | 1821 // Load the payload of the global parameter cell. A hole indicates that the |
| 1821 // cell has been invalidated and that the store must be handled by the | 1822 // cell has been invalidated and that the store must be handled by the |
| 1822 // runtime. | 1823 // runtime. |
| 1823 HValue* cell_contents = Add<HLoadNamedField>(cell, nullptr, access); | 1824 HValue* cell_contents = Add<HLoadNamedField>(cell, nullptr, access); |
| 1824 | 1825 |
| 1825 auto cell_type = stub->cell_type(); | 1826 auto cell_type = stub->cell_type(); |
| 1826 if (cell_type == PropertyCellType::kConstant || | 1827 if (cell_type == PropertyCellType::kConstant || |
| 1827 cell_type == PropertyCellType::kUndefined) { | 1828 cell_type == PropertyCellType::kUndefined) { |
| 1828 // This is always valid for all states a cell can be in. | 1829 // This is always valid for all states a cell can be in. |
| 1829 IfBuilder builder(this); | 1830 IfBuilder builder(this); |
| 1830 builder.If<HCompareObjectEqAndBranch>(cell_contents, value); | 1831 builder.If<HCompareObjectEqAndBranch>(cell_contents, value); |
| 1831 builder.Then(); | 1832 builder.Then(); |
| 1832 builder.ElseDeopt( | 1833 builder.ElseDeopt( |
| 1833 Deoptimizer::kUnexpectedCellContentsInConstantGlobalStore); | 1834 DeoptimizeReason::kUnexpectedCellContentsInConstantGlobalStore); |
| 1834 builder.End(); | 1835 builder.End(); |
| 1835 } else { | 1836 } else { |
| 1836 IfBuilder builder(this); | 1837 IfBuilder builder(this); |
| 1837 HValue* hole_value = graph()->GetConstantHole(); | 1838 HValue* hole_value = graph()->GetConstantHole(); |
| 1838 builder.If<HCompareObjectEqAndBranch>(cell_contents, hole_value); | 1839 builder.If<HCompareObjectEqAndBranch>(cell_contents, hole_value); |
| 1839 builder.Then(); | 1840 builder.Then(); |
| 1840 builder.Deopt(Deoptimizer::kUnexpectedCellContentsInGlobalStore); | 1841 builder.Deopt(DeoptimizeReason::kUnexpectedCellContentsInGlobalStore); |
| 1841 builder.Else(); | 1842 builder.Else(); |
| 1842 // When dealing with constant types, the type may be allowed to change, as | 1843 // When dealing with constant types, the type may be allowed to change, as |
| 1843 // long as optimized code remains valid. | 1844 // long as optimized code remains valid. |
| 1844 if (cell_type == PropertyCellType::kConstantType) { | 1845 if (cell_type == PropertyCellType::kConstantType) { |
| 1845 switch (stub->constant_type()) { | 1846 switch (stub->constant_type()) { |
| 1846 case PropertyCellConstantType::kSmi: | 1847 case PropertyCellConstantType::kSmi: |
| 1847 access = access.WithRepresentation(Representation::Smi()); | 1848 access = access.WithRepresentation(Representation::Smi()); |
| 1848 break; | 1849 break; |
| 1849 case PropertyCellConstantType::kStableMap: { | 1850 case PropertyCellConstantType::kStableMap: { |
| 1850 // It is sufficient here to check that the value and cell contents | 1851 // It is sufficient here to check that the value and cell contents |
| 1851 // have identical maps, no matter if they are stable or not or if they | 1852 // have identical maps, no matter if they are stable or not or if they |
| 1852 // are the maps that were originally in the cell or not. If optimized | 1853 // are the maps that were originally in the cell or not. If optimized |
| 1853 // code will deopt when a cell has a unstable map and if it has a | 1854 // code will deopt when a cell has a unstable map and if it has a |
| 1854 // dependency on a stable map, it will deopt if the map destabilizes. | 1855 // dependency on a stable map, it will deopt if the map destabilizes. |
| 1855 Add<HCheckHeapObject>(value); | 1856 Add<HCheckHeapObject>(value); |
| 1856 Add<HCheckHeapObject>(cell_contents); | 1857 Add<HCheckHeapObject>(cell_contents); |
| 1857 HValue* expected_map = Add<HLoadNamedField>(cell_contents, nullptr, | 1858 HValue* expected_map = Add<HLoadNamedField>(cell_contents, nullptr, |
| 1858 HObjectAccess::ForMap()); | 1859 HObjectAccess::ForMap()); |
| 1859 HValue* map = | 1860 HValue* map = |
| 1860 Add<HLoadNamedField>(value, nullptr, HObjectAccess::ForMap()); | 1861 Add<HLoadNamedField>(value, nullptr, HObjectAccess::ForMap()); |
| 1861 IfBuilder map_check(this); | 1862 IfBuilder map_check(this); |
| 1862 map_check.IfNot<HCompareObjectEqAndBranch>(expected_map, map); | 1863 map_check.IfNot<HCompareObjectEqAndBranch>(expected_map, map); |
| 1863 map_check.ThenDeopt(Deoptimizer::kUnknownMap); | 1864 map_check.ThenDeopt(DeoptimizeReason::kUnknownMap); |
| 1864 map_check.End(); | 1865 map_check.End(); |
| 1865 access = access.WithRepresentation(Representation::HeapObject()); | 1866 access = access.WithRepresentation(Representation::HeapObject()); |
| 1866 break; | 1867 break; |
| 1867 } | 1868 } |
| 1868 } | 1869 } |
| 1869 } | 1870 } |
| 1870 Add<HStoreNamedField>(cell, access, value); | 1871 Add<HStoreNamedField>(cell, access, value); |
| 1871 builder.End(); | 1872 builder.End(); |
| 1872 } | 1873 } |
| 1873 | 1874 |
| 1874 return value; | 1875 return value; |
| 1875 } | 1876 } |
| 1876 | 1877 |
| 1877 | 1878 |
| 1878 Handle<Code> StoreGlobalStub::GenerateCode() { | 1879 Handle<Code> StoreGlobalStub::GenerateCode() { |
| 1879 return DoGenerateCode(this); | 1880 return DoGenerateCode(this); |
| 1880 } | 1881 } |
| 1881 | 1882 |
| 1882 | 1883 |
| 1883 template <> | 1884 template <> |
| 1884 HValue* CodeStubGraphBuilder<ElementsTransitionAndStoreStub>::BuildCodeStub() { | 1885 HValue* CodeStubGraphBuilder<ElementsTransitionAndStoreStub>::BuildCodeStub() { |
| 1885 HValue* object = GetParameter(StoreTransitionHelper::ReceiverIndex()); | 1886 HValue* object = GetParameter(StoreTransitionHelper::ReceiverIndex()); |
| 1886 HValue* key = GetParameter(StoreTransitionHelper::NameIndex()); | 1887 HValue* key = GetParameter(StoreTransitionHelper::NameIndex()); |
| 1887 HValue* value = GetParameter(StoreTransitionHelper::ValueIndex()); | 1888 HValue* value = GetParameter(StoreTransitionHelper::ValueIndex()); |
| 1888 HValue* map = GetParameter(StoreTransitionHelper::MapIndex()); | 1889 HValue* map = GetParameter(StoreTransitionHelper::MapIndex()); |
| 1889 | 1890 |
| 1890 if (FLAG_trace_elements_transitions) { | 1891 if (FLAG_trace_elements_transitions) { |
| 1891 // Tracing elements transitions is the job of the runtime. | 1892 // Tracing elements transitions is the job of the runtime. |
| 1892 Add<HDeoptimize>(Deoptimizer::kTracingElementsTransitions, | 1893 Add<HDeoptimize>(DeoptimizeReason::kTracingElementsTransitions, |
| 1893 Deoptimizer::EAGER); | 1894 Deoptimizer::EAGER); |
| 1894 } else { | 1895 } else { |
| 1895 info()->MarkAsSavesCallerDoubles(); | 1896 info()->MarkAsSavesCallerDoubles(); |
| 1896 | 1897 |
| 1897 BuildTransitionElementsKind(object, map, | 1898 BuildTransitionElementsKind(object, map, |
| 1898 casted_stub()->from_kind(), | 1899 casted_stub()->from_kind(), |
| 1899 casted_stub()->to_kind(), | 1900 casted_stub()->to_kind(), |
| 1900 casted_stub()->is_jsarray()); | 1901 casted_stub()->is_jsarray()); |
| 1901 | 1902 |
| 1902 BuildUncheckedMonomorphicElementAccess(object, key, value, | 1903 BuildUncheckedMonomorphicElementAccess(object, key, value, |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2077 Push(BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash)); | 2078 Push(BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash)); |
| 2078 } | 2079 } |
| 2079 kind_if.Else(); | 2080 kind_if.Else(); |
| 2080 | 2081 |
| 2081 // The SLOW_SLOPPY_ARGUMENTS_ELEMENTS check generates a "kind_if.Then" | 2082 // The SLOW_SLOPPY_ARGUMENTS_ELEMENTS check generates a "kind_if.Then" |
| 2082 STATIC_ASSERT(FAST_SLOPPY_ARGUMENTS_ELEMENTS < | 2083 STATIC_ASSERT(FAST_SLOPPY_ARGUMENTS_ELEMENTS < |
| 2083 SLOW_SLOPPY_ARGUMENTS_ELEMENTS); | 2084 SLOW_SLOPPY_ARGUMENTS_ELEMENTS); |
| 2084 BuildElementsKindLimitCheck(&kind_if, bit_field2, | 2085 BuildElementsKindLimitCheck(&kind_if, bit_field2, |
| 2085 SLOW_SLOPPY_ARGUMENTS_ELEMENTS); | 2086 SLOW_SLOPPY_ARGUMENTS_ELEMENTS); |
| 2086 // Non-strict elements are not handled. | 2087 // Non-strict elements are not handled. |
| 2087 Add<HDeoptimize>(Deoptimizer::kNonStrictElementsInKeyedLoadGenericStub, | 2088 Add<HDeoptimize>(DeoptimizeReason::kNonStrictElementsInKeyedLoadGenericStub, |
| 2088 Deoptimizer::EAGER); | 2089 Deoptimizer::EAGER); |
| 2089 Push(graph()->GetConstant0()); | 2090 Push(graph()->GetConstant0()); |
| 2090 | 2091 |
| 2091 kind_if.ElseDeopt( | 2092 kind_if.ElseDeopt( |
| 2092 Deoptimizer::kElementsKindUnhandledInKeyedLoadGenericStub); | 2093 DeoptimizeReason::kElementsKindUnhandledInKeyedLoadGenericStub); |
| 2093 | 2094 |
| 2094 kind_if.End(); | 2095 kind_if.End(); |
| 2095 } | 2096 } |
| 2096 index_name_split.Else(); | 2097 index_name_split.Else(); |
| 2097 { | 2098 { |
| 2098 // Key is a unique string. | 2099 // Key is a unique string. |
| 2099 key = Pop(); | 2100 key = Pop(); |
| 2100 | 2101 |
| 2101 int bit_field_mask = (1 << Map::kIsAccessCheckNeeded) | | 2102 int bit_field_mask = (1 << Map::kIsAccessCheckNeeded) | |
| 2102 (1 << Map::kHasNamedInterceptor); | 2103 (1 << Map::kHasNamedInterceptor); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2207 return Pop(); | 2208 return Pop(); |
| 2208 } | 2209 } |
| 2209 | 2210 |
| 2210 | 2211 |
| 2211 Handle<Code> KeyedLoadGenericStub::GenerateCode() { | 2212 Handle<Code> KeyedLoadGenericStub::GenerateCode() { |
| 2212 return DoGenerateCode(this); | 2213 return DoGenerateCode(this); |
| 2213 } | 2214 } |
| 2214 | 2215 |
| 2215 } // namespace internal | 2216 } // namespace internal |
| 2216 } // namespace v8 | 2217 } // namespace v8 |
| OLD | NEW |