Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: third_party/WebKit/Source/wtf/Vector.h

Issue 2696123002: WTF::Vector: Add comments to each member function. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. 2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
3 * 3 *
4 * This library is free software; you can redistribute it and/or 4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public 5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either 6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version. 7 * version 2 of the License, or (at your option) any later version.
8 * 8 *
9 * This library is distributed in the hope that it will be useful, 9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
(...skipping 818 matching lines...) Expand 10 before | Expand all | Expand 10 after
829 // Heap-allocated vectors with no inlineCapacity never need a destructor. 829 // Heap-allocated vectors with no inlineCapacity never need a destructor.
830 public ConditionalDestructor<Vector<T, INLINE_CAPACITY, Allocator>, 830 public ConditionalDestructor<Vector<T, INLINE_CAPACITY, Allocator>,
831 (INLINE_CAPACITY == 0) && 831 (INLINE_CAPACITY == 0) &&
832 Allocator::isGarbageCollected> { 832 Allocator::isGarbageCollected> {
833 USE_ALLOCATOR(Vector, Allocator); 833 USE_ALLOCATOR(Vector, Allocator);
834 using Base = VectorBuffer<T, INLINE_CAPACITY, Allocator>; 834 using Base = VectorBuffer<T, INLINE_CAPACITY, Allocator>;
835 using TypeOperations = VectorTypeOperations<T>; 835 using TypeOperations = VectorTypeOperations<T>;
836 using OffsetRange = typename Base::OffsetRange; 836 using OffsetRange = typename Base::OffsetRange;
837 837
838 public: 838 public:
839 typedef T ValueType; 839 using ValueType = T;
840 typedef T value_type; 840 using value_type = T;
841 841
842 typedef T* iterator; 842 using iterator = T*;
843 typedef const T* const_iterator; 843 using const_iterator = const T*;
844 typedef std::reverse_iterator<iterator> reverse_iterator; 844 using reverse_iterator = std::reverse_iterator<iterator>;
845 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 845 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
846 846
847 Vector() { 847 // Create an empty vector.
848 static_assert(!std::is_polymorphic<T>::value || 848 inline Vector();
849 !VectorTraits<T>::canInitializeWithMemset, 849 // Create a vector containing the specified number of default-initialized
850 "Cannot initialize with memset if there is a vtable"); 850 // elements.
851 static_assert(Allocator::isGarbageCollected || 851 inline explicit Vector(size_t);
852 !AllowsOnlyPlacementNew<T>::value || 852 // Create a vector containing the specified number of elements, each of which
853 !IsTraceable<T>::value, 853 // is copy initialized from the specified value.
854 "Cannot put DISALLOW_NEW_EXCEPT_PLACEMENT_NEW objects that " 854 inline Vector(size_t, const T&);
855 "have trace methods into an off-heap Vector");
856 static_assert(Allocator::isGarbageCollected ||
857 !IsPointerToGarbageCollectedType<T>::value,
858 "Cannot put raw pointers to garbage-collected classes into "
859 "an off-heap Vector. Use HeapVector<Member<T>> instead.");
860 855
861 ANNOTATE_NEW_BUFFER(begin(), capacity(), 0); 856 // Copying.
862 m_size = 0;
863 }
864
865 explicit Vector(size_t size) : Base(size) {
866 static_assert(!std::is_polymorphic<T>::value ||
867 !VectorTraits<T>::canInitializeWithMemset,
868 "Cannot initialize with memset if there is a vtable");
869 static_assert(Allocator::isGarbageCollected ||
870 !AllowsOnlyPlacementNew<T>::value ||
871 !IsTraceable<T>::value,
872 "Cannot put DISALLOW_NEW_EXCEPT_PLACEMENT_NEW objects that "
873 "have trace methods into an off-heap Vector");
874 static_assert(Allocator::isGarbageCollected ||
875 !IsPointerToGarbageCollectedType<T>::value,
876 "Cannot put raw pointers to garbage-collected classes into "
877 "an off-heap Vector. Use HeapVector<Member<T>> instead.");
878
879 ANNOTATE_NEW_BUFFER(begin(), capacity(), size);
880 m_size = size;
881 TypeOperations::initialize(begin(), end());
882 }
883
884 // Off-GC-heap vectors: Destructor should be called.
885 // On-GC-heap vectors: Destructor should be called for inline buffers (if
886 // any) but destructor shouldn't be called for vector backing since it is
887 // managed by the traced GC heap.
888 void finalize() {
889 if (!INLINE_CAPACITY) {
890 if (LIKELY(!Base::buffer()))
891 return;
892 }
893 ANNOTATE_DELETE_BUFFER(begin(), capacity(), m_size);
894 if (LIKELY(m_size) &&
895 !(Allocator::isGarbageCollected && this->hasOutOfLineBuffer())) {
896 TypeOperations::destruct(begin(), end());
897 m_size = 0; // Partial protection against use-after-free.
898 }
899
900 Base::destruct();
901 }
902
903 void finalizeGarbageCollectedObject() { finalize(); }
904
905 Vector(const Vector&); 857 Vector(const Vector&);
906 template <size_t otherCapacity> 858 template <size_t otherCapacity>
907 explicit Vector(const Vector<T, otherCapacity, Allocator>&); 859 explicit Vector(const Vector<T, otherCapacity, Allocator>&);
908 860
909 Vector& operator=(const Vector&); 861 Vector& operator=(const Vector&);
910 template <size_t otherCapacity> 862 template <size_t otherCapacity>
911 Vector& operator=(const Vector<T, otherCapacity, Allocator>&); 863 Vector& operator=(const Vector<T, otherCapacity, Allocator>&);
912 864
865 // Moving.
913 Vector(Vector&&); 866 Vector(Vector&&);
914 Vector& operator=(Vector&&); 867 Vector& operator=(Vector&&);
915 868
869 // Construct with an initializer list. You can do e.g.
870 // Vector<int> v({1, 2, 3});
871 // or
872 // v = {4, 5, 6};
916 Vector(std::initializer_list<T> elements); 873 Vector(std::initializer_list<T> elements);
917 Vector& operator=(std::initializer_list<T> elements); 874 Vector& operator=(std::initializer_list<T> elements);
918 875
876 // Basic inquiry about the vector's state.
877 //
878 // capacity() is the maximum number of elements that the Vector can hold
879 // without a reallocation. It can be zero.
919 size_t size() const { return m_size; } 880 size_t size() const { return m_size; }
920 size_t capacity() const { return Base::capacity(); } 881 size_t capacity() const { return Base::capacity(); }
921 bool isEmpty() const { return !size(); } 882 bool isEmpty() const { return !size(); }
922 883
884 // at() and operator[]: Obtain the reference of the element that is located
885 // at the given index. The reference may be invalidated on a reallocation.
886 //
haraken 2017/02/15 07:31:41 Add a comment and explain that we prefer using an
Yuta Kitamura 2017/02/15 10:01:38 This does not really make sense. I'm rather oppose
887 // TODO(yutak): Why do we need both?
haraken 2017/02/15 07:31:41 If |vector| is a pointer, we want to write like:
Yuta Kitamura 2017/02/15 10:01:39 Hmm okay. This does not seem like a clear win, tho
923 T& at(size_t i) { 888 T& at(size_t i) {
924 RELEASE_ASSERT(i < size()); 889 RELEASE_ASSERT(i < size());
925 return Base::buffer()[i]; 890 return Base::buffer()[i];
926 } 891 }
927 const T& at(size_t i) const { 892 const T& at(size_t i) const {
928 RELEASE_ASSERT(i < size()); 893 RELEASE_ASSERT(i < size());
929 return Base::buffer()[i]; 894 return Base::buffer()[i];
930 } 895 }
931 896
932 T& operator[](size_t i) { return at(i); } 897 T& operator[](size_t i) { return at(i); }
933 const T& operator[](size_t i) const { return at(i); } 898 const T& operator[](size_t i) const { return at(i); }
934 899
900 // Return a pointer to the front of the backing buffer. Those pointers get
901 // invalidated on a reallocation.
haraken 2017/02/15 07:31:41 // You should not hold a returned pointer because
Yuta Kitamura 2017/02/15 10:01:38 I'll mention those aspects in the class-level docu
935 T* data() { return Base::buffer(); } 902 T* data() { return Base::buffer(); }
936 const T* data() const { return Base::buffer(); } 903 const T* data() const { return Base::buffer(); }
937 904
905 // Iterators and reverse iterators. They are invalidated on a reallocation.
938 iterator begin() { return data(); } 906 iterator begin() { return data(); }
939 iterator end() { return begin() + m_size; } 907 iterator end() { return begin() + m_size; }
940 const_iterator begin() const { return data(); } 908 const_iterator begin() const { return data(); }
941 const_iterator end() const { return begin() + m_size; } 909 const_iterator end() const { return begin() + m_size; }
942 910
943 reverse_iterator rbegin() { return reverse_iterator(end()); } 911 reverse_iterator rbegin() { return reverse_iterator(end()); }
944 reverse_iterator rend() { return reverse_iterator(begin()); } 912 reverse_iterator rend() { return reverse_iterator(begin()); }
945 const_reverse_iterator rbegin() const { 913 const_reverse_iterator rbegin() const {
946 return const_reverse_iterator(end()); 914 return const_reverse_iterator(end());
947 } 915 }
948 const_reverse_iterator rend() const { 916 const_reverse_iterator rend() const {
949 return const_reverse_iterator(begin()); 917 return const_reverse_iterator(begin());
950 } 918 }
951 919
920 // Quick access to the first and the last element. It is invalid to call
921 // these functions when the vector is empty.
952 T& front() { return at(0); } 922 T& front() { return at(0); }
953 const T& front() const { return at(0); } 923 const T& front() const { return at(0); }
954 T& back() { return at(size() - 1); } 924 T& back() { return at(size() - 1); }
955 const T& back() const { return at(size() - 1); } 925 const T& back() const { return at(size() - 1); }
956 926
927 // Searching.
928 //
929 // Comparisons are done in terms of compareElement(), which is usually
930 // operator==(). find() and reverseFind() returns an index of the element
931 // that is found first. If no match is found, kNotFound will be returned.
957 template <typename U> 932 template <typename U>
958 bool contains(const U&) const; 933 bool contains(const U&) const;
959 template <typename U> 934 template <typename U>
960 size_t find(const U&) const; 935 size_t find(const U&) const;
961 template <typename U> 936 template <typename U>
962 size_t reverseFind(const U&) const; 937 size_t reverseFind(const U&) const;
963 938
939 // Resize the vector to the specified size.
940 //
941 // These three functions are essentially similar. They differ in that
942 // (1) shrink() has a DCHECK to make sure the specified size is not more than
943 // size(), and (2) grow() has a DCHECK to make sure the specified size is
944 // not less than size().
945 //
946 // When a vector shrinks, the extra elements in the back will be destructed.
947 // All the iterators pointing to a to-be-destructed element will be
948 // invalidated.
949 //
950 // When a vector grows, new elements will be added in the back, and they
951 // will be default-initialized. A reallocation may happen in this case.
964 void shrink(size_t); 952 void shrink(size_t);
965 void grow(size_t); 953 void grow(size_t);
966 void resize(size_t); 954 void resize(size_t);
955
956 // Increase the capacity of the vector to at least |newCapacity|. The
957 // elements in the vector are not affected. This function does not shrink
958 // the size of the backing buffer, even if |newCapacity| is small. This
959 // function may cause a reallocation.
967 void reserveCapacity(size_t newCapacity); 960 void reserveCapacity(size_t newCapacity);
961
962 // This is similar to reserveCapacity() but must be called immediately after
963 // the vector is default-constructed.
968 void reserveInitialCapacity(size_t initialCapacity); 964 void reserveInitialCapacity(size_t initialCapacity);
haraken 2017/02/15 07:31:41 Is this really worth having? Can we just use reser
Yuta Kitamura 2017/02/15 10:01:39 The implementation is much simpler, and there are
965
966 // Shrink the backing buffer so it can contain exactly |size()| elements.
967 // This function may cause a reallocation.
969 void shrinkToFit() { shrinkCapacity(size()); } 968 void shrinkToFit() { shrinkCapacity(size()); }
969
970 // Shrink the backing buffer if at least 50% of the vector's capacity is
971 // unused. If it shrinks, the new buffer contains roughly 25% of unused
972 // space. This function may cause a reallocation.
970 void shrinkToReasonableCapacity() { 973 void shrinkToReasonableCapacity() {
971 if (size() * 2 < capacity()) 974 if (size() * 2 < capacity())
972 shrinkCapacity(size() + size() / 4 + 1); 975 shrinkCapacity(size() + size() / 4 + 1);
973 } 976 }
974 977
978 // Remove all the elements. This function actually releases the backing
979 // buffer, thus any iterators will get invalidated (including begin()).
975 void clear() { shrinkCapacity(0); } 980 void clear() { shrinkCapacity(0); }
976 981
977 template <typename U> 982 // Insertion to the back. All of these functions except uncheckedAppend() may
978 void append(const U*, size_t); 983 // cause a reallocation.
984 //
985 // push_back(value)
986 // Insert a single element to the back.
987 // emplace_back(args...)
988 // Insert a single element constructed as T(args...) to the back. The
989 // element is constructed directly on the backing buffer with placement
990 // new.
991 // append(buffer, size)
992 // appendVector(vector)
993 // appendRange(begin, end)
994 // Insert multiple elements represented by (1) |buffer| and |size|
995 // (for append), (2) |vector| (for appendVector), or (3) a pair of
996 // iterators (for appendRange) to the back. The elements will be copied.
997 // uncheckedAppend(value)
998 // Insert a single element like push_back(), but this function assumes
999 // the vector has enough capacity such that it can store the new element
1000 // without a reallocation. Using this function could improve the
1001 // performance when you append many elements repeatedly.
979 template <typename U> 1002 template <typename U>
980 void push_back(U&&); 1003 void push_back(U&&);
981 template <typename... Args> 1004 template <typename... Args>
982 T& emplace_back(Args&&...); 1005 T& emplace_back(Args&&...);
983 template <typename U> 1006 template <typename U>
984 void uncheckedAppend(U&& val); 1007 void append(const U*, size_t);
985 template <typename U, size_t otherCapacity, typename V> 1008 template <typename U, size_t otherCapacity, typename V>
986 void appendVector(const Vector<U, otherCapacity, V>&); 1009 void appendVector(const Vector<U, otherCapacity, V>&);
1010 template <typename Iterator>
1011 void appendRange(Iterator begin, Iterator end);
1012 template <typename U>
1013 void uncheckedAppend(U&&);
987 1014
1015 // Insertion to an arbitrary position. All of these functions will take
1016 // O(size())-time. All of the elements after |position| will be moved to
1017 // the new locations. |position| must be no more than size(). All of these
1018 // functions may cause a reallocation. In any case, all the iterators
1019 // pointing to an element after |position| will be invalidated.
1020 //
1021 // insert(position, value)
1022 // Insert a single element at |position|.
1023 // insert(position, buffer, size)
1024 // insert(position, vector)
1025 // Insert multiple elements represented by either |buffer| and |size|
1026 // or |vector| at |position|. The elements will be copied.
1027 //
1028 // TODO(yutak): Why not insertVector()?
1029 template <typename U>
1030 void insert(size_t position, U&&);
988 template <typename U> 1031 template <typename U>
989 void insert(size_t position, const U*, size_t); 1032 void insert(size_t position, const U*, size_t);
1033 template <typename U, size_t otherCapacity, typename OtherAllocator>
1034 void insert(size_t position, const Vector<U, otherCapacity, OtherAllocator>&);
1035
1036 // Insertion to the front. All of these functions will take O(size())-time.
1037 // All of the elements in the vector will be moved to the new locations.
1038 // All of these functions may cause a reallocation. In any case, all the
1039 // iterators pointing to any element in the vector will be invalidated.
1040 //
1041 // prepend(value)
1042 // Insert a single element to the front.
1043 // prepend(buffer, size)
1044 // prependVector(vector)
1045 // Insert multiple elements represented by either |buffer| and |size| or
1046 // |vector| to the front. The elements will be copied.
990 template <typename U> 1047 template <typename U>
991 void insert(size_t position, U&&); 1048 void prepend(U&&);
992 template <typename U, size_t c, typename V>
993 void insert(size_t position, const Vector<U, c, V>&);
994
995 template <typename U> 1049 template <typename U>
996 void prepend(const U*, size_t); 1050 void prepend(const U*, size_t);
997 template <typename U> 1051 template <typename U, size_t otherCapacity, typename OtherAllocator>
998 void prepend(U&&); 1052 void prependVector(const Vector<U, otherCapacity, OtherAllocator>&);
999 template <typename U, size_t c, typename V>
1000 void prependVector(const Vector<U, c, V>&);
1001 1053
1054 // Remove an element or elements at the specified position. These functions
1055 // take O(size())-time. All of the elements after the removed ones will be
1056 // moved to the new locations. All the iterators pointing to any element
1057 // after |position| will be invalidated.
1002 void remove(size_t position); 1058 void remove(size_t position);
1003 void remove(size_t position, size_t length); 1059 void remove(size_t position, size_t length);
1004 1060
1061 // Remove the last element. Unlike remove(), (1) this function is fast, and
1062 // (2) only iterators pointing to the last element will be invalidated. Other
1063 // references will remain valid.
1005 void pop_back() { 1064 void pop_back() {
1006 DCHECK(!isEmpty()); 1065 DCHECK(!isEmpty());
1007 shrink(size() - 1); 1066 shrink(size() - 1);
1008 } 1067 }
1009 1068
1010 Vector(size_t size, const T& val) : Base(size) { 1069 // Filling the vector with the same value. If the vector has shrinked or
1011 ANNOTATE_NEW_BUFFER(begin(), capacity(), size); 1070 // growed as a result of this call, those events may invalidate some
1012 m_size = size; 1071 // iterators. See comments for shrink() and grow().
1013 TypeOperations::uninitializedFill(begin(), end(), val); 1072 //
1014 } 1073 // fill(value, size) will resize the Vector to |size|, and then copy-assign
1015 1074 // or copy-initialize all the elements.
1075 //
1076 // fill(value) is a synonym for fill(value, size()).
1016 void fill(const T&, size_t); 1077 void fill(const T&, size_t);
1017 void fill(const T& val) { fill(val, size()); } 1078 void fill(const T& val) { fill(val, size()); }
1018 1079
1019 template <typename Iterator> 1080 // Swap two vectors quickly.
1020 void appendRange(Iterator start, Iterator end);
1021
1022 void swap(Vector& other) { 1081 void swap(Vector& other) {
1023 Base::swapVectorBuffer(other, OffsetRange(), OffsetRange()); 1082 Base::swapVectorBuffer(other, OffsetRange(), OffsetRange());
1024 } 1083 }
1025 1084
1085 // Reverse the contents.
1026 void reverse(); 1086 void reverse();
1027 1087
1028 // Maximum element count supported; allocating a vector 1088 // Maximum element count supported; allocating a vector
1029 // buffer with a larger count will fail. 1089 // buffer with a larger count will fail.
1030 static size_t maxCapacity() { 1090 static size_t maxCapacity() {
1031 return Allocator::template maxElementCountInBackingStore<T>(); 1091 return Allocator::template maxElementCountInBackingStore<T>();
1032 } 1092 }
1033 1093
1094 // Off-GC-heap vectors: Destructor should be called.
1095 // On-GC-heap vectors: Destructor should be called for inline buffers (if
1096 // any) but destructor shouldn't be called for vector backing since it is
1097 // managed by the traced GC heap.
1098 void finalize() {
1099 if (!INLINE_CAPACITY) {
1100 if (LIKELY(!Base::buffer()))
1101 return;
1102 }
1103 ANNOTATE_DELETE_BUFFER(begin(), capacity(), m_size);
1104 if (LIKELY(m_size) &&
1105 !(Allocator::isGarbageCollected && this->hasOutOfLineBuffer())) {
1106 TypeOperations::destruct(begin(), end());
1107 m_size = 0; // Partial protection against use-after-free.
1108 }
1109
1110 Base::destruct();
1111 }
1112
1113 void finalizeGarbageCollectedObject() { finalize(); }
1114
1034 template <typename VisitorDispatcher> 1115 template <typename VisitorDispatcher>
1035 void trace(VisitorDispatcher); 1116 void trace(VisitorDispatcher);
1036 1117
1037 class GCForbiddenScope { 1118 class GCForbiddenScope {
1038 STACK_ALLOCATED(); 1119 STACK_ALLOCATED();
1039 1120
1040 public: 1121 public:
1041 GCForbiddenScope() { Allocator::enterGCForbiddenScope(); } 1122 GCForbiddenScope() { Allocator::enterGCForbiddenScope(); }
1042 ~GCForbiddenScope() { Allocator::leaveGCForbiddenScope(); } 1123 ~GCForbiddenScope() { Allocator::leaveGCForbiddenScope(); }
1043 }; 1124 };
(...skipping 20 matching lines...) Expand all
1064 using Base::swapVectorBuffer; 1145 using Base::swapVectorBuffer;
1065 using Base::allocateBuffer; 1146 using Base::allocateBuffer;
1066 using Base::allocationSize; 1147 using Base::allocationSize;
1067 }; 1148 };
1068 1149
1069 // 1150 //
1070 // Vector out-of-line implementation 1151 // Vector out-of-line implementation
1071 // 1152 //
1072 1153
1073 template <typename T, size_t inlineCapacity, typename Allocator> 1154 template <typename T, size_t inlineCapacity, typename Allocator>
1155 inline Vector<T, inlineCapacity, Allocator>::Vector() {
1156 static_assert(!std::is_polymorphic<T>::value ||
1157 !VectorTraits<T>::canInitializeWithMemset,
1158 "Cannot initialize with memset if there is a vtable");
1159 static_assert(Allocator::isGarbageCollected ||
1160 !AllowsOnlyPlacementNew<T>::value || !IsTraceable<T>::value,
1161 "Cannot put DISALLOW_NEW_EXCEPT_PLACEMENT_NEW objects that "
1162 "have trace methods into an off-heap Vector");
1163 static_assert(Allocator::isGarbageCollected ||
1164 !IsPointerToGarbageCollectedType<T>::value,
1165 "Cannot put raw pointers to garbage-collected classes into "
1166 "an off-heap Vector. Use HeapVector<Member<T>> instead.");
1167
1168 ANNOTATE_NEW_BUFFER(begin(), capacity(), 0);
1169 m_size = 0;
1170 }
1171
1172 template <typename T, size_t inlineCapacity, typename Allocator>
1173 inline Vector<T, inlineCapacity, Allocator>::Vector(size_t size) : Base(size) {
1174 static_assert(!std::is_polymorphic<T>::value ||
1175 !VectorTraits<T>::canInitializeWithMemset,
1176 "Cannot initialize with memset if there is a vtable");
1177 static_assert(Allocator::isGarbageCollected ||
1178 !AllowsOnlyPlacementNew<T>::value || !IsTraceable<T>::value,
1179 "Cannot put DISALLOW_NEW_EXCEPT_PLACEMENT_NEW objects that "
1180 "have trace methods into an off-heap Vector");
1181 static_assert(Allocator::isGarbageCollected ||
1182 !IsPointerToGarbageCollectedType<T>::value,
1183 "Cannot put raw pointers to garbage-collected classes into "
1184 "an off-heap Vector. Use HeapVector<Member<T>> instead.");
1185
1186 ANNOTATE_NEW_BUFFER(begin(), capacity(), size);
1187 m_size = size;
1188 TypeOperations::initialize(begin(), end());
1189 }
1190
1191 template <typename T, size_t inlineCapacity, typename Allocator>
1192 inline Vector<T, inlineCapacity, Allocator>::Vector(size_t size, const T& val)
1193 : Base(size) {
1194 // TODO(yutak): Introduce these assertions. Some use sites call this function
1195 // in the context where T is an incomplete type.
1196 //
1197 // static_assert(!std::is_polymorphic<T>::value ||
1198 // !VectorTraits<T>::canInitializeWithMemset,
1199 // "Cannot initialize with memset if there is a vtable");
1200 // static_assert(Allocator::isGarbageCollected ||
1201 // !AllowsOnlyPlacementNew<T>::value ||
1202 // !IsTraceable<T>::value,
1203 // "Cannot put DISALLOW_NEW_EXCEPT_PLACEMENT_NEW objects that "
1204 // "have trace methods into an off-heap Vector");
1205 // static_assert(Allocator::isGarbageCollected ||
1206 // !IsPointerToGarbageCollectedType<T>::value,
1207 // "Cannot put raw pointers to garbage-collected classes into "
1208 // "an off-heap Vector. Use HeapVector<Member<T>> instead.");
1209
1210 ANNOTATE_NEW_BUFFER(begin(), capacity(), size);
1211 m_size = size;
1212 TypeOperations::uninitializedFill(begin(), end(), val);
1213 }
1214
1215 template <typename T, size_t inlineCapacity, typename Allocator>
1074 Vector<T, inlineCapacity, Allocator>::Vector(const Vector& other) 1216 Vector<T, inlineCapacity, Allocator>::Vector(const Vector& other)
1075 : Base(other.capacity()) { 1217 : Base(other.capacity()) {
1076 ANNOTATE_NEW_BUFFER(begin(), capacity(), other.size()); 1218 ANNOTATE_NEW_BUFFER(begin(), capacity(), other.size());
1077 m_size = other.size(); 1219 m_size = other.size();
1078 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); 1220 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
1079 } 1221 }
1080 1222
1081 template <typename T, size_t inlineCapacity, typename Allocator> 1223 template <typename T, size_t inlineCapacity, typename Allocator>
1082 template <size_t otherCapacity> 1224 template <size_t otherCapacity>
1083 Vector<T, inlineCapacity, Allocator>::Vector( 1225 Vector<T, inlineCapacity, Allocator>::Vector(
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1224 DCHECK(begin()); 1366 DCHECK(begin());
1225 } 1367 }
1226 1368
1227 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize); 1369 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize);
1228 std::fill(begin(), end(), val); 1370 std::fill(begin(), end(), val);
1229 TypeOperations::uninitializedFill(end(), begin() + newSize, val); 1371 TypeOperations::uninitializedFill(end(), begin() + newSize, val);
1230 m_size = newSize; 1372 m_size = newSize;
1231 } 1373 }
1232 1374
1233 template <typename T, size_t inlineCapacity, typename Allocator> 1375 template <typename T, size_t inlineCapacity, typename Allocator>
1234 template <typename Iterator>
1235 void Vector<T, inlineCapacity, Allocator>::appendRange(Iterator start,
1236 Iterator end) {
1237 for (Iterator it = start; it != end; ++it)
1238 push_back(*it);
1239 }
1240
1241 template <typename T, size_t inlineCapacity, typename Allocator>
1242 void Vector<T, inlineCapacity, Allocator>::expandCapacity( 1376 void Vector<T, inlineCapacity, Allocator>::expandCapacity(
1243 size_t newMinCapacity) { 1377 size_t newMinCapacity) {
1244 size_t oldCapacity = capacity(); 1378 size_t oldCapacity = capacity();
1245 size_t expandedCapacity = oldCapacity; 1379 size_t expandedCapacity = oldCapacity;
1246 // We use a more aggressive expansion strategy for Vectors with inline 1380 // We use a more aggressive expansion strategy for Vectors with inline
1247 // storage. This is because they are more likely to be on the stack, so the 1381 // storage. This is because they are more likely to be on the stack, so the
1248 // risk of heap bloat is minimized. Furthermore, exceeding the inline 1382 // risk of heap bloat is minimized. Furthermore, exceeding the inline
1249 // capacity limit is not supposed to happen in the common case and may 1383 // capacity limit is not supposed to happen in the common case and may
1250 // indicate a pathological condition or microbenchmark. 1384 // indicate a pathological condition or microbenchmark.
1251 if (INLINE_CAPACITY) { 1385 if (INLINE_CAPACITY) {
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
1400 1534
1401 Base::deallocateBuffer(oldBuffer); 1535 Base::deallocateBuffer(oldBuffer);
1402 } 1536 }
1403 1537
1404 // Templatizing these is better than just letting the conversion happen 1538 // Templatizing these is better than just letting the conversion happen
1405 // implicitly, because for instance it allows a PassRefPtr to be appended to a 1539 // implicitly, because for instance it allows a PassRefPtr to be appended to a
1406 // RefPtr vector without refcount thrash. 1540 // RefPtr vector without refcount thrash.
1407 1541
1408 template <typename T, size_t inlineCapacity, typename Allocator> 1542 template <typename T, size_t inlineCapacity, typename Allocator>
1409 template <typename U> 1543 template <typename U>
1410 void Vector<T, inlineCapacity, Allocator>::append(const U* data,
1411 size_t dataSize) {
1412 DCHECK(Allocator::isAllocationAllowed());
1413 size_t newSize = m_size + dataSize;
1414 if (newSize > capacity()) {
1415 data = expandCapacity(newSize, data);
1416 DCHECK(begin());
1417 }
1418 RELEASE_ASSERT(newSize >= m_size);
1419 T* dest = end();
1420 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize);
1421 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(
1422 data, &data[dataSize], dest);
1423 m_size = newSize;
1424 }
1425
1426 template <typename T, size_t inlineCapacity, typename Allocator>
1427 template <typename U>
1428 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::push_back(U&& val) { 1544 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::push_back(U&& val) {
1429 DCHECK(Allocator::isAllocationAllowed()); 1545 DCHECK(Allocator::isAllocationAllowed());
1430 if (LIKELY(size() != capacity())) { 1546 if (LIKELY(size() != capacity())) {
1431 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); 1547 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1);
1432 new (NotNull, end()) T(std::forward<U>(val)); 1548 new (NotNull, end()) T(std::forward<U>(val));
1433 ++m_size; 1549 ++m_size;
1434 return; 1550 return;
1435 } 1551 }
1436 1552
1437 appendSlowCase(std::forward<U>(val)); 1553 appendSlowCase(std::forward<U>(val));
(...skipping 11 matching lines...) Expand all
1449 expandCapacity(size() + 1); 1565 expandCapacity(size() + 1);
1450 1566
1451 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); 1567 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1);
1452 T* t = new (NotNull, end()) T(std::forward<Args>(args)...); 1568 T* t = new (NotNull, end()) T(std::forward<Args>(args)...);
1453 ++m_size; 1569 ++m_size;
1454 return *t; 1570 return *t;
1455 } 1571 }
1456 1572
1457 template <typename T, size_t inlineCapacity, typename Allocator> 1573 template <typename T, size_t inlineCapacity, typename Allocator>
1458 template <typename U> 1574 template <typename U>
1575 void Vector<T, inlineCapacity, Allocator>::append(const U* data,
1576 size_t dataSize) {
1577 DCHECK(Allocator::isAllocationAllowed());
1578 size_t newSize = m_size + dataSize;
1579 if (newSize > capacity()) {
1580 data = expandCapacity(newSize, data);
1581 DCHECK(begin());
1582 }
1583 RELEASE_ASSERT(newSize >= m_size);
1584 T* dest = end();
1585 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize);
1586 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(
1587 data, &data[dataSize], dest);
1588 m_size = newSize;
1589 }
1590
1591 template <typename T, size_t inlineCapacity, typename Allocator>
1592 template <typename U>
1459 NEVER_INLINE void Vector<T, inlineCapacity, Allocator>::appendSlowCase( 1593 NEVER_INLINE void Vector<T, inlineCapacity, Allocator>::appendSlowCase(
1460 U&& val) { 1594 U&& val) {
1461 DCHECK_EQ(size(), capacity()); 1595 DCHECK_EQ(size(), capacity());
1462 1596
1463 typename std::remove_reference<U>::type* ptr = &val; 1597 typename std::remove_reference<U>::type* ptr = &val;
1464 ptr = expandCapacity(size() + 1, ptr); 1598 ptr = expandCapacity(size() + 1, ptr);
1465 DCHECK(begin()); 1599 DCHECK(begin());
1466 1600
1467 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); 1601 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1);
1468 new (NotNull, end()) T(std::forward<U>(*ptr)); 1602 new (NotNull, end()) T(std::forward<U>(*ptr));
1469 ++m_size; 1603 ++m_size;
1470 } 1604 }
1471 1605
1606 template <typename T, size_t inlineCapacity, typename Allocator>
1607 template <typename U, size_t otherCapacity, typename OtherAllocator>
1608 inline void Vector<T, inlineCapacity, Allocator>::appendVector(
1609 const Vector<U, otherCapacity, OtherAllocator>& val) {
1610 append(val.begin(), val.size());
1611 }
1612
1613 template <typename T, size_t inlineCapacity, typename Allocator>
1614 template <typename Iterator>
1615 void Vector<T, inlineCapacity, Allocator>::appendRange(Iterator begin,
1616 Iterator end) {
1617 for (Iterator it = begin; it != end; ++it)
1618 push_back(*it);
1619 }
1620
1472 // This version of append saves a branch in the case where you know that the 1621 // This version of append saves a branch in the case where you know that the
1473 // vector's capacity is large enough for the append to succeed. 1622 // vector's capacity is large enough for the append to succeed.
1474
1475 template <typename T, size_t inlineCapacity, typename Allocator> 1623 template <typename T, size_t inlineCapacity, typename Allocator>
1476 template <typename U> 1624 template <typename U>
1477 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::uncheckedAppend( 1625 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::uncheckedAppend(
1478 U&& val) { 1626 U&& val) {
1479 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER 1627 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER
1480 // Vectors in ASAN builds don't have inlineCapacity. 1628 // Vectors in ASAN builds don't have inlineCapacity.
1481 push_back(std::forward<U>(val)); 1629 push_back(std::forward<U>(val));
1482 #else 1630 #else
1483 DCHECK_LT(size(), capacity()); 1631 DCHECK_LT(size(), capacity());
1484 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); 1632 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1);
1485 new (NotNull, end()) T(std::forward<U>(val)); 1633 new (NotNull, end()) T(std::forward<U>(val));
1486 ++m_size; 1634 ++m_size;
1487 #endif 1635 #endif
1488 } 1636 }
1489 1637
1490 template <typename T, size_t inlineCapacity, typename Allocator> 1638 template <typename T, size_t inlineCapacity, typename Allocator>
1491 template <typename U, size_t otherCapacity, typename OtherAllocator> 1639 template <typename U>
1492 inline void Vector<T, inlineCapacity, Allocator>::appendVector( 1640 inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position,
1493 const Vector<U, otherCapacity, OtherAllocator>& val) { 1641 U&& val) {
1494 append(val.begin(), val.size()); 1642 DCHECK(Allocator::isAllocationAllowed());
1643 RELEASE_ASSERT(position <= size());
1644 typename std::remove_reference<U>::type* data = &val;
1645 if (size() == capacity()) {
1646 data = expandCapacity(size() + 1, data);
1647 DCHECK(begin());
1648 }
1649 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1);
1650 T* spot = begin() + position;
1651 TypeOperations::moveOverlapping(spot, end(), spot + 1);
1652 new (NotNull, spot) T(std::forward<U>(*data));
1653 ++m_size;
1495 } 1654 }
1496 1655
1497 template <typename T, size_t inlineCapacity, typename Allocator> 1656 template <typename T, size_t inlineCapacity, typename Allocator>
1498 template <typename U> 1657 template <typename U>
1499 void Vector<T, inlineCapacity, Allocator>::insert(size_t position, 1658 void Vector<T, inlineCapacity, Allocator>::insert(size_t position,
1500 const U* data, 1659 const U* data,
1501 size_t dataSize) { 1660 size_t dataSize) {
1502 DCHECK(Allocator::isAllocationAllowed()); 1661 DCHECK(Allocator::isAllocationAllowed());
1503 RELEASE_ASSERT(position <= size()); 1662 RELEASE_ASSERT(position <= size());
1504 size_t newSize = m_size + dataSize; 1663 size_t newSize = m_size + dataSize;
1505 if (newSize > capacity()) { 1664 if (newSize > capacity()) {
1506 data = expandCapacity(newSize, data); 1665 data = expandCapacity(newSize, data);
1507 DCHECK(begin()); 1666 DCHECK(begin());
1508 } 1667 }
1509 RELEASE_ASSERT(newSize >= m_size); 1668 RELEASE_ASSERT(newSize >= m_size);
1510 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize); 1669 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize);
1511 T* spot = begin() + position; 1670 T* spot = begin() + position;
1512 TypeOperations::moveOverlapping(spot, end(), spot + dataSize); 1671 TypeOperations::moveOverlapping(spot, end(), spot + dataSize);
1513 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy( 1672 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(
1514 data, &data[dataSize], spot); 1673 data, &data[dataSize], spot);
1515 m_size = newSize; 1674 m_size = newSize;
1516 } 1675 }
1517 1676
1518 template <typename T, size_t inlineCapacity, typename Allocator> 1677 template <typename T, size_t inlineCapacity, typename Allocator>
1678 template <typename U, size_t otherCapacity, typename OtherAllocator>
1679 inline void Vector<T, inlineCapacity, Allocator>::insert(
1680 size_t position,
1681 const Vector<U, otherCapacity, OtherAllocator>& val) {
1682 insert(position, val.begin(), val.size());
1683 }
1684
1685 template <typename T, size_t inlineCapacity, typename Allocator>
1519 template <typename U> 1686 template <typename U>
1520 inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, 1687 inline void Vector<T, inlineCapacity, Allocator>::prepend(U&& val) {
1521 U&& val) { 1688 insert(0, std::forward<U>(val));
1522 DCHECK(Allocator::isAllocationAllowed());
1523 RELEASE_ASSERT(position <= size());
1524 typename std::remove_reference<U>::type* data = &val;
1525 if (size() == capacity()) {
1526 data = expandCapacity(size() + 1, data);
1527 DCHECK(begin());
1528 }
1529 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1);
1530 T* spot = begin() + position;
1531 TypeOperations::moveOverlapping(spot, end(), spot + 1);
1532 new (NotNull, spot) T(std::forward<U>(*data));
1533 ++m_size;
1534 }
1535
1536 template <typename T, size_t inlineCapacity, typename Allocator>
1537 template <typename U, size_t c, typename OtherAllocator>
1538 inline void Vector<T, inlineCapacity, Allocator>::insert(
1539 size_t position,
1540 const Vector<U, c, OtherAllocator>& val) {
1541 insert(position, val.begin(), val.size());
1542 } 1689 }
1543 1690
1544 template <typename T, size_t inlineCapacity, typename Allocator> 1691 template <typename T, size_t inlineCapacity, typename Allocator>
1545 template <typename U> 1692 template <typename U>
1546 void Vector<T, inlineCapacity, Allocator>::prepend(const U* data, 1693 void Vector<T, inlineCapacity, Allocator>::prepend(const U* data,
1547 size_t dataSize) { 1694 size_t dataSize) {
1548 insert(0, data, dataSize); 1695 insert(0, data, dataSize);
1549 } 1696 }
1550 1697
1551 template <typename T, size_t inlineCapacity, typename Allocator> 1698 template <typename T, size_t inlineCapacity, typename Allocator>
1552 template <typename U> 1699 template <typename U, size_t otherCapacity, typename OtherAllocator>
1553 inline void Vector<T, inlineCapacity, Allocator>::prepend(U&& val) {
1554 insert(0, std::forward<U>(val));
1555 }
1556
1557 template <typename T, size_t inlineCapacity, typename Allocator>
1558 template <typename U, size_t c, typename V>
1559 inline void Vector<T, inlineCapacity, Allocator>::prependVector( 1700 inline void Vector<T, inlineCapacity, Allocator>::prependVector(
1560 const Vector<U, c, V>& val) { 1701 const Vector<U, otherCapacity, OtherAllocator>& val) {
1561 insert(0, val.begin(), val.size()); 1702 insert(0, val.begin(), val.size());
1562 } 1703 }
1563 1704
1564 template <typename T, size_t inlineCapacity, typename Allocator> 1705 template <typename T, size_t inlineCapacity, typename Allocator>
1565 inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position) { 1706 inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position) {
1566 RELEASE_ASSERT(position < size()); 1707 RELEASE_ASSERT(position < size());
1567 T* spot = begin() + position; 1708 T* spot = begin() + position;
1568 spot->~T(); 1709 spot->~T();
1569 TypeOperations::moveOverlapping(spot + 1, end(), spot); 1710 TypeOperations::moveOverlapping(spot + 1, end(), spot);
1570 clearUnusedSlots(end() - 1, end()); 1711 clearUnusedSlots(end() - 1, end());
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1649 visitor, *const_cast<T*>(bufferEntry)); 1790 visitor, *const_cast<T*>(bufferEntry));
1650 checkUnusedSlots(buffer() + size(), buffer() + capacity()); 1791 checkUnusedSlots(buffer() + size(), buffer() + capacity());
1651 } 1792 }
1652 } 1793 }
1653 1794
1654 } // namespace WTF 1795 } // namespace WTF
1655 1796
1656 using WTF::Vector; 1797 using WTF::Vector;
1657 1798
1658 #endif // WTF_Vector_h 1799 #endif // WTF_Vector_h
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698