| 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 |