OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/ic/keyed-store-generic.h" | 5 #include "src/ic/keyed-store-generic.h" |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/code-stub-assembler.h" | 8 #include "src/code-stub-assembler.h" |
9 #include "src/contexts.h" | 9 #include "src/contexts.h" |
10 #include "src/ic/accessor-assembler.h" | 10 #include "src/ic/accessor-assembler.h" |
11 #include "src/interface-descriptors.h" | 11 #include "src/interface-descriptors.h" |
12 #include "src/isolate.h" | 12 #include "src/isolate.h" |
13 #include "src/objects-inl.h" | 13 #include "src/objects-inl.h" |
14 | 14 |
15 namespace v8 { | 15 namespace v8 { |
16 namespace internal { | 16 namespace internal { |
17 | 17 |
18 using compiler::Node; | 18 using compiler::Node; |
19 | 19 |
20 class KeyedStoreGenericAssembler : public AccessorAssembler { | 20 class KeyedStoreGenericAssembler : public AccessorAssembler { |
21 public: | 21 public: |
22 explicit KeyedStoreGenericAssembler(compiler::CodeAssemblerState* state) | 22 explicit KeyedStoreGenericAssembler(compiler::CodeAssemblerState* state) |
23 : AccessorAssembler(state) {} | 23 : AccessorAssembler(state) {} |
24 | 24 |
25 void KeyedStoreGeneric(LanguageMode language_mode); | 25 void KeyedStoreGeneric(LanguageMode language_mode); |
26 | 26 |
| 27 void StoreIC_Uninitialized(LanguageMode language_mode); |
| 28 |
27 private: | 29 private: |
28 enum UpdateLength { | 30 enum UpdateLength { |
29 kDontChangeLength, | 31 kDontChangeLength, |
30 kIncrementLengthByOne, | 32 kIncrementLengthByOne, |
31 kBumpLengthWithGap | 33 kBumpLengthWithGap |
32 }; | 34 }; |
33 | 35 |
| 36 enum UseStubCache { kUseStubCache, kDontUseStubCache }; |
| 37 |
34 void EmitGenericElementStore(Node* receiver, Node* receiver_map, | 38 void EmitGenericElementStore(Node* receiver, Node* receiver_map, |
35 Node* instance_type, Node* intptr_index, | 39 Node* instance_type, Node* intptr_index, |
36 Node* value, Node* context, Label* slow); | 40 Node* value, Node* context, Label* slow); |
37 | 41 |
38 void EmitGenericPropertyStore(Node* receiver, Node* receiver_map, | 42 void EmitGenericPropertyStore(Node* receiver, Node* receiver_map, |
39 const StoreICParameters* p, Label* slow, | 43 const StoreICParameters* p, Label* slow, |
40 LanguageMode language_mode); | 44 LanguageMode language_mode, |
| 45 UseStubCache use_stub_cache = kUseStubCache); |
41 | 46 |
42 void BranchIfPrototypesHaveNonFastElements(Node* receiver_map, | 47 void BranchIfPrototypesHaveNonFastElements(Node* receiver_map, |
43 Label* non_fast_elements, | 48 Label* non_fast_elements, |
44 Label* only_fast_elements); | 49 Label* only_fast_elements); |
45 | 50 |
46 void TryRewriteElements(Node* receiver, Node* receiver_map, Node* elements, | 51 void TryRewriteElements(Node* receiver, Node* receiver_map, Node* elements, |
47 Node* native_context, ElementsKind from_kind, | 52 Node* native_context, ElementsKind from_kind, |
48 ElementsKind to_kind, Label* bailout); | 53 ElementsKind to_kind, Label* bailout); |
49 | 54 |
50 void StoreElementWithCapacity(Node* receiver, Node* receiver_map, | 55 void StoreElementWithCapacity(Node* receiver, Node* receiver_map, |
(...skipping 29 matching lines...) Expand all Loading... |
80 Node* descriptor_name_index, Node* details, | 85 Node* descriptor_name_index, Node* details, |
81 Node* value, Label* slow); | 86 Node* value, Label* slow); |
82 }; | 87 }; |
83 | 88 |
84 void KeyedStoreGenericGenerator::Generate(compiler::CodeAssemblerState* state, | 89 void KeyedStoreGenericGenerator::Generate(compiler::CodeAssemblerState* state, |
85 LanguageMode language_mode) { | 90 LanguageMode language_mode) { |
86 KeyedStoreGenericAssembler assembler(state); | 91 KeyedStoreGenericAssembler assembler(state); |
87 assembler.KeyedStoreGeneric(language_mode); | 92 assembler.KeyedStoreGeneric(language_mode); |
88 } | 93 } |
89 | 94 |
| 95 void StoreICUninitializedGenerator::Generate( |
| 96 compiler::CodeAssemblerState* state, LanguageMode language_mode) { |
| 97 KeyedStoreGenericAssembler assembler(state); |
| 98 assembler.StoreIC_Uninitialized(language_mode); |
| 99 } |
| 100 |
90 void KeyedStoreGenericAssembler::BranchIfPrototypesHaveNonFastElements( | 101 void KeyedStoreGenericAssembler::BranchIfPrototypesHaveNonFastElements( |
91 Node* receiver_map, Label* non_fast_elements, Label* only_fast_elements) { | 102 Node* receiver_map, Label* non_fast_elements, Label* only_fast_elements) { |
92 Variable var_map(this, MachineRepresentation::kTagged); | 103 Variable var_map(this, MachineRepresentation::kTagged); |
93 var_map.Bind(receiver_map); | 104 var_map.Bind(receiver_map); |
94 Label loop_body(this, &var_map); | 105 Label loop_body(this, &var_map); |
95 Goto(&loop_body); | 106 Goto(&loop_body); |
96 | 107 |
97 Bind(&loop_body); | 108 Bind(&loop_body); |
98 { | 109 { |
99 Node* map = var_map.value(); | 110 Node* map = var_map.value(); |
(...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
731 { | 742 { |
732 StoreFixedArrayElement(properties, backing_store_index, value); | 743 StoreFixedArrayElement(properties, backing_store_index, value); |
733 Goto(&done); | 744 Goto(&done); |
734 } | 745 } |
735 } | 746 } |
736 Bind(&done); | 747 Bind(&done); |
737 } | 748 } |
738 | 749 |
739 void KeyedStoreGenericAssembler::EmitGenericPropertyStore( | 750 void KeyedStoreGenericAssembler::EmitGenericPropertyStore( |
740 Node* receiver, Node* receiver_map, const StoreICParameters* p, Label* slow, | 751 Node* receiver, Node* receiver_map, const StoreICParameters* p, Label* slow, |
741 LanguageMode language_mode) { | 752 LanguageMode language_mode, UseStubCache use_stub_cache) { |
742 Variable var_accessor_pair(this, MachineRepresentation::kTagged); | 753 Variable var_accessor_pair(this, MachineRepresentation::kTagged); |
743 Variable var_accessor_holder(this, MachineRepresentation::kTagged); | 754 Variable var_accessor_holder(this, MachineRepresentation::kTagged); |
744 Label stub_cache(this), fast_properties(this), dictionary_properties(this), | 755 Label stub_cache(this), fast_properties(this), dictionary_properties(this), |
745 accessor(this), readonly(this); | 756 accessor(this), readonly(this); |
746 Node* properties = LoadProperties(receiver); | 757 Node* properties = LoadProperties(receiver); |
747 Node* properties_map = LoadMap(properties); | 758 Node* properties_map = LoadMap(properties); |
748 Branch(WordEqual(properties_map, LoadRoot(Heap::kHashTableMapRootIndex)), | 759 Branch(WordEqual(properties_map, LoadRoot(Heap::kHashTableMapRootIndex)), |
749 &dictionary_properties, &fast_properties); | 760 &dictionary_properties, &fast_properties); |
750 | 761 |
751 Bind(&fast_properties); | 762 Bind(&fast_properties); |
752 { | 763 { |
753 Comment("fast property store"); | 764 Comment("fast property store"); |
754 Node* bitfield3 = LoadMapBitField3(receiver_map); | 765 Node* bitfield3 = LoadMapBitField3(receiver_map); |
755 Node* descriptors = LoadMapDescriptors(receiver_map); | 766 Node* descriptors = LoadMapDescriptors(receiver_map); |
756 Label descriptor_found(this); | 767 Label descriptor_found(this); |
757 Variable var_name_index(this, MachineType::PointerRepresentation()); | 768 Variable var_name_index(this, MachineType::PointerRepresentation()); |
758 // TODO(jkummerow): Maybe look for existing map transitions? | 769 // TODO(jkummerow): Maybe look for existing map transitions? |
759 Label* notfound = &stub_cache; | 770 Label* notfound = use_stub_cache == kUseStubCache ? &stub_cache : slow; |
760 DescriptorLookup(p->name, descriptors, bitfield3, &descriptor_found, | 771 DescriptorLookup(p->name, descriptors, bitfield3, &descriptor_found, |
761 &var_name_index, notfound); | 772 &var_name_index, notfound); |
762 | 773 |
763 Bind(&descriptor_found); | 774 Bind(&descriptor_found); |
764 { | 775 { |
765 Node* name_index = var_name_index.value(); | 776 Node* name_index = var_name_index.value(); |
766 Node* details = | 777 Node* details = |
767 LoadDetailsByKeyIndex<DescriptorArray>(descriptors, name_index); | 778 LoadDetailsByKeyIndex<DescriptorArray>(descriptors, name_index); |
768 Label data_property(this); | 779 Label data_property(this); |
769 JumpIfDataProperty(details, &data_property, &readonly); | 780 JumpIfDataProperty(details, &data_property, &readonly); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
812 Bind(&overwrite); | 823 Bind(&overwrite); |
813 { | 824 { |
814 StoreValueByKeyIndex<NameDictionary>(properties, var_name_index.value(), | 825 StoreValueByKeyIndex<NameDictionary>(properties, var_name_index.value(), |
815 p->value); | 826 p->value); |
816 Return(p->value); | 827 Return(p->value); |
817 } | 828 } |
818 } | 829 } |
819 | 830 |
820 Bind(¬_found); | 831 Bind(¬_found); |
821 { | 832 { |
| 833 Label extensible(this); |
| 834 GotoIf(IsPrivateSymbol(p->name), &extensible); |
| 835 Node* bitfield2 = LoadMapBitField2(receiver_map); |
| 836 Branch(IsSetWord32(bitfield2, 1 << Map::kIsExtensible), &extensible, |
| 837 slow); |
| 838 |
| 839 Bind(&extensible); |
822 LookupPropertyOnPrototypeChain(receiver_map, p->name, &accessor, | 840 LookupPropertyOnPrototypeChain(receiver_map, p->name, &accessor, |
823 &var_accessor_pair, &var_accessor_holder, | 841 &var_accessor_pair, &var_accessor_holder, |
824 &readonly, slow); | 842 &readonly, slow); |
825 Add<NameDictionary>(properties, p->name, p->value, slow); | 843 Add<NameDictionary>(properties, p->name, p->value, slow); |
826 Return(p->value); | 844 Return(p->value); |
827 } | 845 } |
828 } | 846 } |
829 | 847 |
830 Bind(&accessor); | 848 Bind(&accessor); |
831 { | 849 { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
864 SmiConstant(Smi::FromInt(MessageTemplate::kStrictReadOnlyProperty)); | 882 SmiConstant(Smi::FromInt(MessageTemplate::kStrictReadOnlyProperty)); |
865 Node* type = Typeof(p->receiver); | 883 Node* type = Typeof(p->receiver); |
866 TailCallRuntime(Runtime::kThrowTypeError, p->context, message, p->name, | 884 TailCallRuntime(Runtime::kThrowTypeError, p->context, message, p->name, |
867 type, p->receiver); | 885 type, p->receiver); |
868 } else { | 886 } else { |
869 DCHECK_EQ(SLOPPY, language_mode); | 887 DCHECK_EQ(SLOPPY, language_mode); |
870 Return(p->value); | 888 Return(p->value); |
871 } | 889 } |
872 } | 890 } |
873 | 891 |
874 Bind(&stub_cache); | 892 if (use_stub_cache == kUseStubCache) { |
875 { | 893 Bind(&stub_cache); |
876 Comment("stub cache probe"); | 894 Comment("stub cache probe"); |
877 Variable var_handler(this, MachineRepresentation::kTagged); | 895 Variable var_handler(this, MachineRepresentation::kTagged); |
878 Label found_handler(this, &var_handler), stub_cache_miss(this); | 896 Label found_handler(this, &var_handler), stub_cache_miss(this); |
879 TryProbeStubCache(isolate()->store_stub_cache(), receiver, p->name, | 897 TryProbeStubCache(isolate()->store_stub_cache(), receiver, p->name, |
880 &found_handler, &var_handler, &stub_cache_miss); | 898 &found_handler, &var_handler, &stub_cache_miss); |
881 Bind(&found_handler); | 899 Bind(&found_handler); |
882 { | 900 { |
883 Comment("KeyedStoreGeneric found handler"); | 901 Comment("KeyedStoreGeneric found handler"); |
884 HandleStoreICHandlerCase(p, var_handler.value(), &stub_cache_miss); | 902 HandleStoreICHandlerCase(p, var_handler.value(), &stub_cache_miss); |
885 } | 903 } |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
934 } | 952 } |
935 | 953 |
936 Bind(&slow); | 954 Bind(&slow); |
937 { | 955 { |
938 Comment("KeyedStoreGeneric_slow"); | 956 Comment("KeyedStoreGeneric_slow"); |
939 TailCallRuntime(Runtime::kSetProperty, context, receiver, name, value, | 957 TailCallRuntime(Runtime::kSetProperty, context, receiver, name, value, |
940 SmiConstant(language_mode)); | 958 SmiConstant(language_mode)); |
941 } | 959 } |
942 } | 960 } |
943 | 961 |
| 962 void KeyedStoreGenericAssembler::StoreIC_Uninitialized( |
| 963 LanguageMode language_mode) { |
| 964 typedef StoreWithVectorDescriptor Descriptor; |
| 965 |
| 966 Node* receiver = Parameter(Descriptor::kReceiver); |
| 967 Node* name = Parameter(Descriptor::kName); |
| 968 Node* value = Parameter(Descriptor::kValue); |
| 969 Node* slot = Parameter(Descriptor::kSlot); |
| 970 Node* vector = Parameter(Descriptor::kVector); |
| 971 Node* context = Parameter(Descriptor::kContext); |
| 972 |
| 973 Label miss(this); |
| 974 |
| 975 GotoIf(TaggedIsSmi(receiver), &miss); |
| 976 Node* receiver_map = LoadMap(receiver); |
| 977 Node* instance_type = LoadMapInstanceType(receiver_map); |
| 978 // Receivers requiring non-standard element accesses (interceptors, access |
| 979 // checks, strings and string wrappers, proxies) are handled in the runtime. |
| 980 GotoIf(Int32LessThanOrEqual(instance_type, |
| 981 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), |
| 982 &miss); |
| 983 |
| 984 // Optimistically write the state transition to the vector. |
| 985 StoreFixedArrayElement(vector, slot, |
| 986 LoadRoot(Heap::kpremonomorphic_symbolRootIndex), |
| 987 SKIP_WRITE_BARRIER, 0, SMI_PARAMETERS); |
| 988 |
| 989 StoreICParameters p(context, receiver, name, value, slot, vector); |
| 990 EmitGenericPropertyStore(receiver, receiver_map, &p, &miss, language_mode, |
| 991 kDontUseStubCache); |
| 992 |
| 993 Bind(&miss); |
| 994 { |
| 995 // Undo the optimistic state transition. |
| 996 StoreFixedArrayElement(vector, slot, |
| 997 LoadRoot(Heap::kuninitialized_symbolRootIndex), |
| 998 SKIP_WRITE_BARRIER, 0, SMI_PARAMETERS); |
| 999 TailCallRuntime(Runtime::kStoreIC_Miss, context, value, slot, vector, |
| 1000 receiver, name); |
| 1001 } |
| 1002 } |
| 1003 |
944 } // namespace internal | 1004 } // namespace internal |
945 } // namespace v8 | 1005 } // namespace v8 |
OLD | NEW |