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 |