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