| 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/accessor-assembler.h" | 5 #include "src/ic/accessor-assembler.h" |
| 6 | 6 |
| 7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
| 9 #include "src/ic/handler-configuration.h" | 9 #include "src/ic/handler-configuration.h" |
| 10 #include "src/ic/stub-cache.h" | 10 #include "src/ic/stub-cache.h" |
| (...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 623 Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word); | 623 Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word); |
| 624 if (transition) { | 624 if (transition) { |
| 625 CSA_ASSERT( | 625 CSA_ASSERT( |
| 626 this, | 626 this, |
| 627 Word32Or( | 627 Word32Or( |
| 628 WordEqual(handler_kind, | 628 WordEqual(handler_kind, |
| 629 IntPtrConstant(StoreHandler::kTransitionToField)), | 629 IntPtrConstant(StoreHandler::kTransitionToField)), |
| 630 WordEqual(handler_kind, | 630 WordEqual(handler_kind, |
| 631 IntPtrConstant(StoreHandler::kTransitionToConstant)))); | 631 IntPtrConstant(StoreHandler::kTransitionToConstant)))); |
| 632 } else { | 632 } else { |
| 633 CSA_ASSERT(this, WordEqual(handler_kind, | 633 if (FLAG_track_constant_fields) { |
| 634 IntPtrConstant(StoreHandler::kStoreField))); | 634 CSA_ASSERT( |
| 635 this, |
| 636 Word32Or(WordEqual(handler_kind, |
| 637 IntPtrConstant(StoreHandler::kStoreField)), |
| 638 WordEqual(handler_kind, |
| 639 IntPtrConstant(StoreHandler::kStoreConstField)))); |
| 640 } else { |
| 641 CSA_ASSERT(this, WordEqual(handler_kind, |
| 642 IntPtrConstant(StoreHandler::kStoreField))); |
| 643 } |
| 635 } | 644 } |
| 636 #endif | 645 #endif |
| 637 | 646 |
| 638 Node* field_representation = | 647 Node* field_representation = |
| 639 DecodeWord<StoreHandler::FieldRepresentationBits>(handler_word); | 648 DecodeWord<StoreHandler::FieldRepresentationBits>(handler_word); |
| 640 | 649 |
| 641 Label if_smi_field(this), if_double_field(this), if_heap_object_field(this), | 650 Label if_smi_field(this), if_double_field(this), if_heap_object_field(this), |
| 642 if_tagged_field(this); | 651 if_tagged_field(this); |
| 643 | 652 |
| 644 GotoIf(WordEqual(field_representation, IntPtrConstant(StoreHandler::kTagged)), | 653 GotoIf(WordEqual(field_representation, IntPtrConstant(StoreHandler::kTagged)), |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 691 Node* prepared_value = PrepareValueForStore( | 700 Node* prepared_value = PrepareValueForStore( |
| 692 handler_word, holder, representation, transition, value, miss); | 701 handler_word, holder, representation, transition, value, miss); |
| 693 | 702 |
| 694 Label if_inobject(this), if_out_of_object(this); | 703 Label if_inobject(this), if_out_of_object(this); |
| 695 Branch(IsSetWord<StoreHandler::IsInobjectBits>(handler_word), &if_inobject, | 704 Branch(IsSetWord<StoreHandler::IsInobjectBits>(handler_word), &if_inobject, |
| 696 &if_out_of_object); | 705 &if_out_of_object); |
| 697 | 706 |
| 698 Bind(&if_inobject); | 707 Bind(&if_inobject); |
| 699 { | 708 { |
| 700 StoreNamedField(handler_word, holder, true, representation, prepared_value, | 709 StoreNamedField(handler_word, holder, true, representation, prepared_value, |
| 701 transition_to_field); | 710 transition_to_field, miss); |
| 702 if (transition_to_field) { | 711 if (transition_to_field) { |
| 703 StoreMap(holder, transition); | 712 StoreMap(holder, transition); |
| 704 } | 713 } |
| 705 Return(value); | 714 Return(value); |
| 706 } | 715 } |
| 707 | 716 |
| 708 Bind(&if_out_of_object); | 717 Bind(&if_out_of_object); |
| 709 { | 718 { |
| 710 if (transition_to_field) { | 719 if (transition_to_field) { |
| 711 Label storage_extended(this); | 720 Label storage_extended(this); |
| 712 GotoUnless(IsSetWord<StoreHandler::ExtendStorageBits>(handler_word), | 721 GotoUnless(IsSetWord<StoreHandler::ExtendStorageBits>(handler_word), |
| 713 &storage_extended); | 722 &storage_extended); |
| 714 Comment("[ Extend storage"); | 723 Comment("[ Extend storage"); |
| 715 ExtendPropertiesBackingStore(holder); | 724 ExtendPropertiesBackingStore(holder); |
| 716 Comment("] Extend storage"); | 725 Comment("] Extend storage"); |
| 717 Goto(&storage_extended); | 726 Goto(&storage_extended); |
| 718 | 727 |
| 719 Bind(&storage_extended); | 728 Bind(&storage_extended); |
| 720 } | 729 } |
| 721 | 730 |
| 722 StoreNamedField(handler_word, holder, false, representation, prepared_value, | 731 StoreNamedField(handler_word, holder, false, representation, prepared_value, |
| 723 transition_to_field); | 732 transition_to_field, miss); |
| 724 if (transition_to_field) { | 733 if (transition_to_field) { |
| 725 StoreMap(holder, transition); | 734 StoreMap(holder, transition); |
| 726 } | 735 } |
| 727 Return(value); | 736 Return(value); |
| 728 } | 737 } |
| 729 } | 738 } |
| 730 | 739 |
| 731 Node* AccessorAssembler::PrepareValueForStore(Node* handler_word, Node* holder, | 740 Node* AccessorAssembler::PrepareValueForStore(Node* handler_word, Node* holder, |
| 732 Representation representation, | 741 Representation representation, |
| 733 Node* transition, Node* value, | 742 Node* transition, Node* value, |
| 734 Label* bailout) { | 743 Label* bailout) { |
| 735 if (representation.IsDouble()) { | 744 if (representation.IsDouble()) { |
| 736 value = TryTaggedToFloat64(value, bailout); | 745 value = TryTaggedToFloat64(value, bailout); |
| 737 | 746 |
| 738 } else if (representation.IsHeapObject()) { | 747 } else if (representation.IsHeapObject()) { |
| 739 GotoIf(TaggedIsSmi(value), bailout); | 748 GotoIf(TaggedIsSmi(value), bailout); |
| 749 |
| 750 Label done(this); |
| 751 if (FLAG_track_constant_fields && !transition) { |
| 752 // Skip field type check in favor of constant value check when storing |
| 753 // to constant field. |
| 754 GotoIf(WordEqual(DecodeWord<StoreHandler::KindBits>(handler_word), |
| 755 IntPtrConstant(StoreHandler::kStoreConstField)), |
| 756 &done); |
| 757 } |
| 740 Node* value_index_in_descriptor = | 758 Node* value_index_in_descriptor = |
| 741 DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word); | 759 DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word); |
| 742 Node* descriptors = | 760 Node* descriptors = |
| 743 LoadMapDescriptors(transition ? transition : LoadMap(holder)); | 761 LoadMapDescriptors(transition ? transition : LoadMap(holder)); |
| 744 Node* maybe_field_type = | 762 Node* maybe_field_type = |
| 745 LoadFixedArrayElement(descriptors, value_index_in_descriptor); | 763 LoadFixedArrayElement(descriptors, value_index_in_descriptor); |
| 746 | 764 |
| 747 Label done(this); | |
| 748 GotoIf(TaggedIsSmi(maybe_field_type), &done); | 765 GotoIf(TaggedIsSmi(maybe_field_type), &done); |
| 749 // Check that value type matches the field type. | 766 // Check that value type matches the field type. |
| 750 { | 767 { |
| 751 Node* field_type = LoadWeakCellValue(maybe_field_type, bailout); | 768 Node* field_type = LoadWeakCellValue(maybe_field_type, bailout); |
| 752 Branch(WordEqual(LoadMap(value), field_type), &done, bailout); | 769 Branch(WordEqual(LoadMap(value), field_type), &done, bailout); |
| 753 } | 770 } |
| 754 Bind(&done); | 771 Bind(&done); |
| 755 | 772 |
| 756 } else if (representation.IsSmi()) { | 773 } else if (representation.IsSmi()) { |
| 757 GotoUnless(TaggedIsSmi(value), bailout); | 774 GotoUnless(TaggedIsSmi(value), bailout); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 794 // the write barrier. | 811 // the write barrier. |
| 795 CopyFixedArrayElements(kind, properties, new_properties, length, | 812 CopyFixedArrayElements(kind, properties, new_properties, length, |
| 796 SKIP_WRITE_BARRIER, mode); | 813 SKIP_WRITE_BARRIER, mode); |
| 797 | 814 |
| 798 StoreObjectField(object, JSObject::kPropertiesOffset, new_properties); | 815 StoreObjectField(object, JSObject::kPropertiesOffset, new_properties); |
| 799 } | 816 } |
| 800 | 817 |
| 801 void AccessorAssembler::StoreNamedField(Node* handler_word, Node* object, | 818 void AccessorAssembler::StoreNamedField(Node* handler_word, Node* object, |
| 802 bool is_inobject, | 819 bool is_inobject, |
| 803 Representation representation, | 820 Representation representation, |
| 804 Node* value, bool transition_to_field) { | 821 Node* value, bool transition_to_field, |
| 822 Label* bailout) { |
| 805 bool store_value_as_double = representation.IsDouble(); | 823 bool store_value_as_double = representation.IsDouble(); |
| 806 Node* property_storage = object; | 824 Node* property_storage = object; |
| 807 if (!is_inobject) { | 825 if (!is_inobject) { |
| 808 property_storage = LoadProperties(object); | 826 property_storage = LoadProperties(object); |
| 809 } | 827 } |
| 810 | 828 |
| 811 Node* offset = DecodeWord<StoreHandler::FieldOffsetBits>(handler_word); | 829 Node* offset = DecodeWord<StoreHandler::FieldOffsetBits>(handler_word); |
| 812 if (representation.IsDouble()) { | 830 if (representation.IsDouble()) { |
| 813 if (!FLAG_unbox_double_fields || !is_inobject) { | 831 if (!FLAG_unbox_double_fields || !is_inobject) { |
| 814 if (transition_to_field) { | 832 if (transition_to_field) { |
| 815 Node* heap_number = AllocateHeapNumberWithValue(value, MUTABLE); | 833 Node* heap_number = AllocateHeapNumberWithValue(value, MUTABLE); |
| 816 // Store the new mutable heap number into the object. | 834 // Store the new mutable heap number into the object. |
| 817 value = heap_number; | 835 value = heap_number; |
| 818 store_value_as_double = false; | 836 store_value_as_double = false; |
| 819 } else { | 837 } else { |
| 820 // Load the heap number. | 838 // Load the heap number. |
| 821 property_storage = LoadObjectField(property_storage, offset); | 839 property_storage = LoadObjectField(property_storage, offset); |
| 822 // Store the double value into it. | 840 // Store the double value into it. |
| 823 offset = IntPtrConstant(HeapNumber::kValueOffset); | 841 offset = IntPtrConstant(HeapNumber::kValueOffset); |
| 824 } | 842 } |
| 825 } | 843 } |
| 826 } | 844 } |
| 827 | 845 |
| 846 // Do constant value check if necessary. |
| 847 if (FLAG_track_constant_fields && !transition_to_field) { |
| 848 Label done(this); |
| 849 GotoUnless(WordEqual(DecodeWord<StoreHandler::KindBits>(handler_word), |
| 850 IntPtrConstant(StoreHandler::kStoreConstField)), |
| 851 &done); |
| 852 { |
| 853 if (store_value_as_double) { |
| 854 Node* current_value = |
| 855 LoadObjectField(property_storage, offset, MachineType::Float64()); |
| 856 GotoUnless(Float64Equal(current_value, value), bailout); |
| 857 } else { |
| 858 Node* current_value = LoadObjectField(property_storage, offset); |
| 859 GotoUnless(WordEqual(current_value, value), bailout); |
| 860 } |
| 861 Goto(&done); |
| 862 } |
| 863 Bind(&done); |
| 864 } |
| 865 |
| 866 // Do the store. |
| 828 if (store_value_as_double) { | 867 if (store_value_as_double) { |
| 829 StoreObjectFieldNoWriteBarrier(property_storage, offset, value, | 868 StoreObjectFieldNoWriteBarrier(property_storage, offset, value, |
| 830 MachineRepresentation::kFloat64); | 869 MachineRepresentation::kFloat64); |
| 831 } else if (representation.IsSmi()) { | 870 } else if (representation.IsSmi()) { |
| 832 StoreObjectFieldNoWriteBarrier(property_storage, offset, value); | 871 StoreObjectFieldNoWriteBarrier(property_storage, offset, value); |
| 833 } else { | 872 } else { |
| 834 StoreObjectField(property_storage, offset, value); | 873 StoreObjectField(property_storage, offset, value); |
| 835 } | 874 } |
| 836 } | 875 } |
| 837 | 876 |
| (...skipping 1045 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1883 Node* slot = Parameter(Descriptor::kSlot); | 1922 Node* slot = Parameter(Descriptor::kSlot); |
| 1884 Node* context = Parameter(Descriptor::kContext); | 1923 Node* context = Parameter(Descriptor::kContext); |
| 1885 Node* vector = LoadTypeFeedbackVectorForStub(); | 1924 Node* vector = LoadTypeFeedbackVectorForStub(); |
| 1886 | 1925 |
| 1887 StoreICParameters p(context, receiver, name, value, slot, vector); | 1926 StoreICParameters p(context, receiver, name, value, slot, vector); |
| 1888 KeyedStoreIC(&p, language_mode); | 1927 KeyedStoreIC(&p, language_mode); |
| 1889 } | 1928 } |
| 1890 | 1929 |
| 1891 } // namespace internal | 1930 } // namespace internal |
| 1892 } // namespace v8 | 1931 } // namespace v8 |
| OLD | NEW |