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 #include "src/ic/accessor-assembler-impl.h" | 6 #include "src/ic/accessor-assembler-impl.h" |
7 | 7 |
8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/ic/handler-configuration.h" | 10 #include "src/ic/handler-configuration.h" |
(...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
663 Bind(&if_double_field); | 663 Bind(&if_double_field); |
664 { | 664 { |
665 Comment("store double field"); | 665 Comment("store double field"); |
666 HandleStoreFieldAndReturn(handler_word, holder, Representation::Double(), | 666 HandleStoreFieldAndReturn(handler_word, holder, Representation::Double(), |
667 value, transition, miss); | 667 value, transition, miss); |
668 } | 668 } |
669 | 669 |
670 Bind(&if_heap_object_field); | 670 Bind(&if_heap_object_field); |
671 { | 671 { |
672 Comment("store heap object field"); | 672 Comment("store heap object field"); |
673 // Generate full field type check here and then store value as Tagged. | 673 // Generate full field type check here and then store value as Tagged. |
Igor Sheludko
2017/01/10 15:11:13
Moved this check to PrepareValueForStore().
| |
674 Node* prepared_value = | 674 Node* prepared_value = |
675 PrepareValueForWrite(value, Representation::HeapObject(), miss); | 675 PrepareValueForWrite(value, Representation::HeapObject(), miss); |
676 Node* value_index_in_descriptor = | 676 Node* value_index_in_descriptor = |
677 DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word); | 677 DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word); |
678 Node* descriptors = | 678 Node* descriptors = |
679 LoadMapDescriptors(transition ? transition : LoadMap(holder)); | 679 LoadMapDescriptors(transition ? transition : LoadMap(holder)); |
680 Node* maybe_field_type = | 680 Node* maybe_field_type = |
681 LoadFixedArrayElement(descriptors, value_index_in_descriptor); | 681 LoadFixedArrayElement(descriptors, value_index_in_descriptor); |
682 Label do_store(this); | 682 Label do_store(this); |
683 GotoIf(TaggedIsSmi(maybe_field_type), &do_store); | 683 GotoIf(TaggedIsSmi(maybe_field_type), &do_store); |
(...skipping 14 matching lines...) Expand all Loading... | |
698 value, transition, miss); | 698 value, transition, miss); |
699 } | 699 } |
700 } | 700 } |
701 | 701 |
702 void AccessorAssemblerImpl::HandleStoreFieldAndReturn( | 702 void AccessorAssemblerImpl::HandleStoreFieldAndReturn( |
703 Node* handler_word, Node* holder, Representation representation, | 703 Node* handler_word, Node* holder, Representation representation, |
704 Node* value, Node* transition, Label* miss) { | 704 Node* value, Node* transition, Label* miss) { |
705 bool transition_to_field = transition != nullptr; | 705 bool transition_to_field = transition != nullptr; |
706 Node* prepared_value = PrepareValueForWrite(value, representation, miss); | 706 Node* prepared_value = PrepareValueForWrite(value, representation, miss); |
707 | 707 |
708 if (transition_to_field) { | 708 if (transition_to_field) { |
Igor Sheludko
2017/01/10 15:11:13
Moved this to if_out_of_object block.
| |
709 Label storage_extended(this); | 709 Label storage_extended(this); |
710 GotoUnless(IsSetWord<StoreHandler::ExtendStorageBits>(handler_word), | 710 GotoUnless(IsSetWord<StoreHandler::ExtendStorageBits>(handler_word), |
711 &storage_extended); | 711 &storage_extended); |
712 Comment("[ Extend storage"); | 712 Comment("[ Extend storage"); |
713 ExtendPropertiesBackingStore(holder); | 713 ExtendPropertiesBackingStore(holder); |
714 Comment("] Extend storage"); | 714 Comment("] Extend storage"); |
715 Goto(&storage_extended); | 715 Goto(&storage_extended); |
716 | 716 |
717 Bind(&storage_extended); | 717 Bind(&storage_extended); |
718 } | 718 } |
(...skipping 17 matching lines...) Expand all Loading... | |
736 { | 736 { |
737 StoreNamedField(holder, offset, false, representation, prepared_value, | 737 StoreNamedField(holder, offset, false, representation, prepared_value, |
738 transition_to_field); | 738 transition_to_field); |
739 if (transition_to_field) { | 739 if (transition_to_field) { |
740 StoreMap(holder, transition); | 740 StoreMap(holder, transition); |
741 } | 741 } |
742 Return(value); | 742 Return(value); |
743 } | 743 } |
744 } | 744 } |
745 | 745 |
746 Node* AccessorAssemblerImpl::PrepareValueForWrite(Node* value, | |
747 Representation representation, | |
748 Label* bailout) { | |
749 if (representation.IsDouble()) { | |
750 value = TryTaggedToFloat64(value, bailout); | |
751 } else if (representation.IsHeapObject()) { | |
752 // Field type is checked by the handler, here we only check if the value | |
753 // is a heap object. | |
754 GotoIf(TaggedIsSmi(value), bailout); | |
755 } else if (representation.IsSmi()) { | |
756 GotoUnless(TaggedIsSmi(value), bailout); | |
757 } else { | |
758 DCHECK(representation.IsTagged()); | |
759 } | |
760 return value; | |
761 } | |
762 | |
763 void AccessorAssemblerImpl::ExtendPropertiesBackingStore(Node* object) { | |
764 Node* properties = LoadProperties(object); | |
765 Node* length = LoadFixedArrayBaseLength(properties); | |
766 | |
767 ParameterMode mode = OptimalParameterMode(); | |
768 length = TaggedToParameter(length, mode); | |
769 | |
770 Node* delta = IntPtrOrSmiConstant(JSObject::kFieldsAdded, mode); | |
771 Node* new_capacity = IntPtrOrSmiAdd(length, delta, mode); | |
772 | |
773 // Grow properties array. | |
774 ElementsKind kind = FAST_ELEMENTS; | |
775 DCHECK(kMaxNumberOfDescriptors + JSObject::kFieldsAdded < | |
776 FixedArrayBase::GetMaxLengthForNewSpaceAllocation(kind)); | |
777 // The size of a new properties backing store is guaranteed to be small | |
778 // enough that the new backing store will be allocated in new space. | |
779 CSA_ASSERT(this, | |
780 UintPtrOrSmiLessThan( | |
781 new_capacity, | |
782 IntPtrOrSmiConstant( | |
783 kMaxNumberOfDescriptors + JSObject::kFieldsAdded, mode), | |
784 mode)); | |
785 | |
786 Node* new_properties = AllocateFixedArray(kind, new_capacity, mode); | |
787 | |
788 FillFixedArrayWithValue(kind, new_properties, length, new_capacity, | |
789 Heap::kUndefinedValueRootIndex, mode); | |
790 | |
791 // |new_properties| is guaranteed to be in new space, so we can skip | |
792 // the write barrier. | |
793 CopyFixedArrayElements(kind, properties, new_properties, length, | |
794 SKIP_WRITE_BARRIER, mode); | |
795 | |
796 StoreObjectField(object, JSObject::kPropertiesOffset, new_properties); | |
797 } | |
798 | |
799 void AccessorAssemblerImpl::StoreNamedField(Node* object, Node* offset, | |
800 bool is_inobject, | |
801 Representation representation, | |
802 Node* value, | |
803 bool transition_to_field) { | |
804 bool store_value_as_double = representation.IsDouble(); | |
805 Node* property_storage = object; | |
806 if (!is_inobject) { | |
807 property_storage = LoadProperties(object); | |
808 } | |
809 | |
810 if (representation.IsDouble()) { | |
811 if (!FLAG_unbox_double_fields || !is_inobject) { | |
812 if (transition_to_field) { | |
813 Node* heap_number = AllocateHeapNumberWithValue(value, MUTABLE); | |
814 // Store the new mutable heap number into the object. | |
815 value = heap_number; | |
816 store_value_as_double = false; | |
817 } else { | |
818 // Load the heap number. | |
819 property_storage = LoadObjectField(property_storage, offset); | |
820 // Store the double value into it. | |
821 offset = IntPtrConstant(HeapNumber::kValueOffset); | |
822 } | |
823 } | |
824 } | |
825 | |
826 if (store_value_as_double) { | |
827 StoreObjectFieldNoWriteBarrier(property_storage, offset, value, | |
828 MachineRepresentation::kFloat64); | |
829 } else if (representation.IsSmi()) { | |
830 StoreObjectFieldNoWriteBarrier(property_storage, offset, value); | |
831 } else { | |
832 StoreObjectField(property_storage, offset, value); | |
833 } | |
834 } | |
835 | |
746 void AccessorAssemblerImpl::EmitFastElementsBoundsCheck( | 836 void AccessorAssemblerImpl::EmitFastElementsBoundsCheck( |
747 Node* object, Node* elements, Node* intptr_index, | 837 Node* object, Node* elements, Node* intptr_index, |
748 Node* is_jsarray_condition, Label* miss) { | 838 Node* is_jsarray_condition, Label* miss) { |
749 Variable var_length(this, MachineType::PointerRepresentation()); | 839 Variable var_length(this, MachineType::PointerRepresentation()); |
750 Comment("Fast elements bounds check"); | 840 Comment("Fast elements bounds check"); |
751 Label if_array(this), length_loaded(this, &var_length); | 841 Label if_array(this), length_loaded(this, &var_length); |
752 GotoIf(is_jsarray_condition, &if_array); | 842 GotoIf(is_jsarray_condition, &if_array); |
753 { | 843 { |
754 var_length.Bind(SmiUntag(LoadFixedArrayBaseLength(elements))); | 844 var_length.Bind(SmiUntag(LoadFixedArrayBaseLength(elements))); |
755 Goto(&length_loaded); | 845 Goto(&length_loaded); |
(...skipping 1071 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1827 void AccessorAssembler::GenerateKeyedStoreICTrampolineTF( | 1917 void AccessorAssembler::GenerateKeyedStoreICTrampolineTF( |
1828 CodeAssemblerState* state, LanguageMode language_mode) { | 1918 CodeAssemblerState* state, LanguageMode language_mode) { |
1829 AccessorAssemblerImpl assembler(state); | 1919 AccessorAssemblerImpl assembler(state); |
1830 assembler.GenerateKeyedStoreICTrampolineTF(language_mode); | 1920 assembler.GenerateKeyedStoreICTrampolineTF(language_mode); |
1831 } | 1921 } |
1832 | 1922 |
1833 #undef ACCESSOR_ASSEMBLER_PUBLIC_INTERFACE | 1923 #undef ACCESSOR_ASSEMBLER_PUBLIC_INTERFACE |
1834 | 1924 |
1835 } // namespace internal | 1925 } // namespace internal |
1836 } // namespace v8 | 1926 } // namespace v8 |
OLD | NEW |