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 |