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

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

Issue 2696123002: WTF::Vector: Add comments to each member function. (Closed)
Patch Set: Mention the use case of at(). 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 //
887 // at() can be used in cases like:
888 // pointerToVector->at(1);
889 // instead of:
890 // (*pointerToVector)[1];
923 T& at(size_t i) { 891 T& at(size_t i) {
924 RELEASE_ASSERT(i < size()); 892 RELEASE_ASSERT(i < size());
925 return Base::buffer()[i]; 893 return Base::buffer()[i];
926 } 894 }
927 const T& at(size_t i) const { 895 const T& at(size_t i) const {
928 RELEASE_ASSERT(i < size()); 896 RELEASE_ASSERT(i < size());
929 return Base::buffer()[i]; 897 return Base::buffer()[i];
930 } 898 }
931 899
932 T& operator[](size_t i) { return at(i); } 900 T& operator[](size_t i) { return at(i); }
933 const T& operator[](size_t i) const { return at(i); } 901 const T& operator[](size_t i) const { return at(i); }
934 902
903 // Return a pointer to the front of the backing buffer. Those pointers get
904 // invalidated on a reallocation.
935 T* data() { return Base::buffer(); } 905 T* data() { return Base::buffer(); }
936 const T* data() const { return Base::buffer(); } 906 const T* data() const { return Base::buffer(); }
937 907
908 // Iterators and reverse iterators. They are invalidated on a reallocation.
938 iterator begin() { return data(); } 909 iterator begin() { return data(); }
939 iterator end() { return begin() + m_size; } 910 iterator end() { return begin() + m_size; }
940 const_iterator begin() const { return data(); } 911 const_iterator begin() const { return data(); }
941 const_iterator end() const { return begin() + m_size; } 912 const_iterator end() const { return begin() + m_size; }
942 913
943 reverse_iterator rbegin() { return reverse_iterator(end()); } 914 reverse_iterator rbegin() { return reverse_iterator(end()); }
944 reverse_iterator rend() { return reverse_iterator(begin()); } 915 reverse_iterator rend() { return reverse_iterator(begin()); }
945 const_reverse_iterator rbegin() const { 916 const_reverse_iterator rbegin() const {
946 return const_reverse_iterator(end()); 917 return const_reverse_iterator(end());
947 } 918 }
948 const_reverse_iterator rend() const { 919 const_reverse_iterator rend() const {
949 return const_reverse_iterator(begin()); 920 return const_reverse_iterator(begin());
950 } 921 }
951 922
923 // Quick access to the first and the last element. It is invalid to call
924 // these functions when the vector is empty.
952 T& front() { return at(0); } 925 T& front() { return at(0); }
953 const T& front() const { return at(0); } 926 const T& front() const { return at(0); }
954 T& back() { return at(size() - 1); } 927 T& back() { return at(size() - 1); }
955 const T& back() const { return at(size() - 1); } 928 const T& back() const { return at(size() - 1); }
956 929
930 // Searching.
931 //
932 // Comparisons are done in terms of compareElement(), which is usually
933 // operator==(). find() and reverseFind() returns an index of the element
934 // that is found first. If no match is found, kNotFound will be returned.
957 template <typename U> 935 template <typename U>
958 bool contains(const U&) const; 936 bool contains(const U&) const;
959 template <typename U> 937 template <typename U>
960 size_t find(const U&) const; 938 size_t find(const U&) const;
961 template <typename U> 939 template <typename U>
962 size_t reverseFind(const U&) const; 940 size_t reverseFind(const U&) const;
963 941
942 // Resize the vector to the specified size.
943 //
944 // These three functions are essentially similar. They differ in that
945 // (1) shrink() has a DCHECK to make sure the specified size is not more than
946 // size(), and (2) grow() has a DCHECK to make sure the specified size is
947 // not less than size().
948 //
949 // When a vector shrinks, the extra elements in the back will be destructed.
950 // All the iterators pointing to a to-be-destructed element will be
951 // invalidated.
952 //
953 // When a vector grows, new elements will be added in the back, and they
954 // will be default-initialized. A reallocation may happen in this case.
964 void shrink(size_t); 955 void shrink(size_t);
965 void grow(size_t); 956 void grow(size_t);
966 void resize(size_t); 957 void resize(size_t);
958
959 // Increase the capacity of the vector to at least |newCapacity|. The
960 // elements in the vector are not affected. This function does not shrink
961 // the size of the backing buffer, even if |newCapacity| is small. This
962 // function may cause a reallocation.
967 void reserveCapacity(size_t newCapacity); 963 void reserveCapacity(size_t newCapacity);
964
965 // This is similar to reserveCapacity() but must be called immediately after
966 // the vector is default-constructed.
968 void reserveInitialCapacity(size_t initialCapacity); 967 void reserveInitialCapacity(size_t initialCapacity);
968
969 // Shrink the backing buffer so it can contain exactly |size()| elements.
970 // This function may cause a reallocation.
969 void shrinkToFit() { shrinkCapacity(size()); } 971 void shrinkToFit() { shrinkCapacity(size()); }
972
973 // Shrink the backing buffer if at least 50% of the vector's capacity is
974 // unused. If it shrinks, the new buffer contains roughly 25% of unused
975 // space. This function may cause a reallocation.
970 void shrinkToReasonableCapacity() { 976 void shrinkToReasonableCapacity() {
971 if (size() * 2 < capacity()) 977 if (size() * 2 < capacity())
972 shrinkCapacity(size() + size() / 4 + 1); 978 shrinkCapacity(size() + size() / 4 + 1);
973 } 979 }
974 980
981 // Remove all the elements. This function actually releases the backing
982 // buffer, thus any iterators will get invalidated (including begin()).
975 void clear() { shrinkCapacity(0); } 983 void clear() { shrinkCapacity(0); }
976 984
977 template <typename U> 985 // Insertion to the back. All of these functions except uncheckedAppend() may
978 void append(const U*, size_t); 986 // cause a reallocation.
987 //
988 // push_back(value)
989 // Insert a single element to the back.
990 // emplace_back(args...)
991 // Insert a single element constructed as T(args...) to the back. The
992 // element is constructed directly on the backing buffer with placement
993 // new.
994 // append(buffer, size)
995 // appendVector(vector)
996 // appendRange(begin, end)
997 // Insert multiple elements represented by (1) |buffer| and |size|
998 // (for append), (2) |vector| (for appendVector), or (3) a pair of
999 // iterators (for appendRange) to the back. The elements will be copied.
1000 // uncheckedAppend(value)
1001 // Insert a single element like push_back(), but this function assumes
1002 // the vector has enough capacity such that it can store the new element
1003 // without a reallocation. Using this function could improve the
1004 // performance when you append many elements repeatedly.
979 template <typename U> 1005 template <typename U>
980 void push_back(U&&); 1006 void push_back(U&&);
981 template <typename... Args> 1007 template <typename... Args>
982 T& emplace_back(Args&&...); 1008 T& emplace_back(Args&&...);
983 template <typename U> 1009 template <typename U>
984 void uncheckedAppend(U&& val); 1010 void append(const U*, size_t);
985 template <typename U, size_t otherCapacity, typename V> 1011 template <typename U, size_t otherCapacity, typename V>
986 void appendVector(const Vector<U, otherCapacity, V>&); 1012 void appendVector(const Vector<U, otherCapacity, V>&);
1013 template <typename Iterator>
1014 void appendRange(Iterator begin, Iterator end);
1015 template <typename U>
1016 void uncheckedAppend(U&&);
987 1017
1018 // Insertion to an arbitrary position. All of these functions will take
1019 // O(size())-time. All of the elements after |position| will be moved to
1020 // the new locations. |position| must be no more than size(). All of these
1021 // functions may cause a reallocation. In any case, all the iterators
1022 // pointing to an element after |position| will be invalidated.
1023 //
1024 // insert(position, value)
1025 // Insert a single element at |position|.
1026 // insert(position, buffer, size)
1027 // insert(position, vector)
1028 // Insert multiple elements represented by either |buffer| and |size|
1029 // or |vector| at |position|. The elements will be copied.
1030 //
1031 // TODO(yutak): Why not insertVector()?
1032 template <typename U>
1033 void insert(size_t position, U&&);
988 template <typename U> 1034 template <typename U>
989 void insert(size_t position, const U*, size_t); 1035 void insert(size_t position, const U*, size_t);
1036 template <typename U, size_t otherCapacity, typename OtherAllocator>
1037 void insert(size_t position, const Vector<U, otherCapacity, OtherAllocator>&);
1038
1039 // Insertion to the front. All of these functions will take O(size())-time.
1040 // All of the elements in the vector will be moved to the new locations.
1041 // All of these functions may cause a reallocation. In any case, all the
1042 // iterators pointing to any element in the vector will be invalidated.
1043 //
1044 // prepend(value)
1045 // Insert a single element to the front.
1046 // prepend(buffer, size)
1047 // prependVector(vector)
1048 // Insert multiple elements represented by either |buffer| and |size| or
1049 // |vector| to the front. The elements will be copied.
990 template <typename U> 1050 template <typename U>
991 void insert(size_t position, U&&); 1051 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> 1052 template <typename U>
996 void prepend(const U*, size_t); 1053 void prepend(const U*, size_t);
997 template <typename U> 1054 template <typename U, size_t otherCapacity, typename OtherAllocator>
998 void prepend(U&&); 1055 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 1056
1057 // Remove an element or elements at the specified position. These functions
1058 // take O(size())-time. All of the elements after the removed ones will be
1059 // moved to the new locations. All the iterators pointing to any element
1060 // after |position| will be invalidated.
1002 void remove(size_t position); 1061 void remove(size_t position);
1003 void remove(size_t position, size_t length); 1062 void remove(size_t position, size_t length);
1004 1063
1064 // Remove the last element. Unlike remove(), (1) this function is fast, and
1065 // (2) only iterators pointing to the last element will be invalidated. Other
1066 // references will remain valid.
1005 void pop_back() { 1067 void pop_back() {
1006 DCHECK(!isEmpty()); 1068 DCHECK(!isEmpty());
1007 shrink(size() - 1); 1069 shrink(size() - 1);
1008 } 1070 }
1009 1071
1010 Vector(size_t size, const T& val) : Base(size) { 1072 // Filling the vector with the same value. If the vector has shrinked or
1011 ANNOTATE_NEW_BUFFER(begin(), capacity(), size); 1073 // growed as a result of this call, those events may invalidate some
1012 m_size = size; 1074 // iterators. See comments for shrink() and grow().
1013 TypeOperations::uninitializedFill(begin(), end(), val); 1075 //
1014 } 1076 // fill(value, size) will resize the Vector to |size|, and then copy-assign
1015 1077 // or copy-initialize all the elements.
1078 //
1079 // fill(value) is a synonym for fill(value, size()).
1016 void fill(const T&, size_t); 1080 void fill(const T&, size_t);
1017 void fill(const T& val) { fill(val, size()); } 1081 void fill(const T& val) { fill(val, size()); }
1018 1082
1019 template <typename Iterator> 1083 // Swap two vectors quickly.
1020 void appendRange(Iterator start, Iterator end);
1021
1022 void swap(Vector& other) { 1084 void swap(Vector& other) {
1023 Base::swapVectorBuffer(other, OffsetRange(), OffsetRange()); 1085 Base::swapVectorBuffer(other, OffsetRange(), OffsetRange());
1024 } 1086 }
1025 1087
1088 // Reverse the contents.
1026 void reverse(); 1089 void reverse();
1027 1090
1028 // Maximum element count supported; allocating a vector 1091 // Maximum element count supported; allocating a vector
1029 // buffer with a larger count will fail. 1092 // buffer with a larger count will fail.
1030 static size_t maxCapacity() { 1093 static size_t maxCapacity() {
1031 return Allocator::template maxElementCountInBackingStore<T>(); 1094 return Allocator::template maxElementCountInBackingStore<T>();
1032 } 1095 }
1033 1096
1097 // Off-GC-heap vectors: Destructor should be called.
1098 // On-GC-heap vectors: Destructor should be called for inline buffers (if
1099 // any) but destructor shouldn't be called for vector backing since it is
1100 // managed by the traced GC heap.
1101 void finalize() {
1102 if (!INLINE_CAPACITY) {
1103 if (LIKELY(!Base::buffer()))
1104 return;
1105 }
1106 ANNOTATE_DELETE_BUFFER(begin(), capacity(), m_size);
1107 if (LIKELY(m_size) &&
1108 !(Allocator::isGarbageCollected && this->hasOutOfLineBuffer())) {
1109 TypeOperations::destruct(begin(), end());
1110 m_size = 0; // Partial protection against use-after-free.
1111 }
1112
1113 Base::destruct();
1114 }
1115
1116 void finalizeGarbageCollectedObject() { finalize(); }
1117
1034 template <typename VisitorDispatcher> 1118 template <typename VisitorDispatcher>
1035 void trace(VisitorDispatcher); 1119 void trace(VisitorDispatcher);
1036 1120
1037 class GCForbiddenScope { 1121 class GCForbiddenScope {
1038 STACK_ALLOCATED(); 1122 STACK_ALLOCATED();
1039 1123
1040 public: 1124 public:
1041 GCForbiddenScope() { Allocator::enterGCForbiddenScope(); } 1125 GCForbiddenScope() { Allocator::enterGCForbiddenScope(); }
1042 ~GCForbiddenScope() { Allocator::leaveGCForbiddenScope(); } 1126 ~GCForbiddenScope() { Allocator::leaveGCForbiddenScope(); }
1043 }; 1127 };
(...skipping 20 matching lines...) Expand all
1064 using Base::swapVectorBuffer; 1148 using Base::swapVectorBuffer;
1065 using Base::allocateBuffer; 1149 using Base::allocateBuffer;
1066 using Base::allocationSize; 1150 using Base::allocationSize;
1067 }; 1151 };
1068 1152
1069 // 1153 //
1070 // Vector out-of-line implementation 1154 // Vector out-of-line implementation
1071 // 1155 //
1072 1156
1073 template <typename T, size_t inlineCapacity, typename Allocator> 1157 template <typename T, size_t inlineCapacity, typename Allocator>
1158 inline Vector<T, inlineCapacity, Allocator>::Vector() {
1159 static_assert(!std::is_polymorphic<T>::value ||
1160 !VectorTraits<T>::canInitializeWithMemset,
1161 "Cannot initialize with memset if there is a vtable");
1162 static_assert(Allocator::isGarbageCollected ||
1163 !AllowsOnlyPlacementNew<T>::value || !IsTraceable<T>::value,
1164 "Cannot put DISALLOW_NEW_EXCEPT_PLACEMENT_NEW objects that "
1165 "have trace methods into an off-heap Vector");
1166 static_assert(Allocator::isGarbageCollected ||
1167 !IsPointerToGarbageCollectedType<T>::value,
1168 "Cannot put raw pointers to garbage-collected classes into "
1169 "an off-heap Vector. Use HeapVector<Member<T>> instead.");
1170
1171 ANNOTATE_NEW_BUFFER(begin(), capacity(), 0);
1172 m_size = 0;
1173 }
1174
1175 template <typename T, size_t inlineCapacity, typename Allocator>
1176 inline Vector<T, inlineCapacity, Allocator>::Vector(size_t size) : Base(size) {
1177 static_assert(!std::is_polymorphic<T>::value ||
1178 !VectorTraits<T>::canInitializeWithMemset,
1179 "Cannot initialize with memset if there is a vtable");
1180 static_assert(Allocator::isGarbageCollected ||
1181 !AllowsOnlyPlacementNew<T>::value || !IsTraceable<T>::value,
1182 "Cannot put DISALLOW_NEW_EXCEPT_PLACEMENT_NEW objects that "
1183 "have trace methods into an off-heap Vector");
1184 static_assert(Allocator::isGarbageCollected ||
1185 !IsPointerToGarbageCollectedType<T>::value,
1186 "Cannot put raw pointers to garbage-collected classes into "
1187 "an off-heap Vector. Use HeapVector<Member<T>> instead.");
1188
1189 ANNOTATE_NEW_BUFFER(begin(), capacity(), size);
1190 m_size = size;
1191 TypeOperations::initialize(begin(), end());
1192 }
1193
1194 template <typename T, size_t inlineCapacity, typename Allocator>
1195 inline Vector<T, inlineCapacity, Allocator>::Vector(size_t size, const T& val)
1196 : Base(size) {
1197 // TODO(yutak): Introduce these assertions. Some use sites call this function
1198 // in the context where T is an incomplete type.
1199 //
1200 // static_assert(!std::is_polymorphic<T>::value ||
1201 // !VectorTraits<T>::canInitializeWithMemset,
1202 // "Cannot initialize with memset if there is a vtable");
1203 // static_assert(Allocator::isGarbageCollected ||
1204 // !AllowsOnlyPlacementNew<T>::value ||
1205 // !IsTraceable<T>::value,
1206 // "Cannot put DISALLOW_NEW_EXCEPT_PLACEMENT_NEW objects that "
1207 // "have trace methods into an off-heap Vector");
1208 // static_assert(Allocator::isGarbageCollected ||
1209 // !IsPointerToGarbageCollectedType<T>::value,
1210 // "Cannot put raw pointers to garbage-collected classes into "
1211 // "an off-heap Vector. Use HeapVector<Member<T>> instead.");
1212
1213 ANNOTATE_NEW_BUFFER(begin(), capacity(), size);
1214 m_size = size;
1215 TypeOperations::uninitializedFill(begin(), end(), val);
1216 }
1217
1218 template <typename T, size_t inlineCapacity, typename Allocator>
1074 Vector<T, inlineCapacity, Allocator>::Vector(const Vector& other) 1219 Vector<T, inlineCapacity, Allocator>::Vector(const Vector& other)
1075 : Base(other.capacity()) { 1220 : Base(other.capacity()) {
1076 ANNOTATE_NEW_BUFFER(begin(), capacity(), other.size()); 1221 ANNOTATE_NEW_BUFFER(begin(), capacity(), other.size());
1077 m_size = other.size(); 1222 m_size = other.size();
1078 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); 1223 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
1079 } 1224 }
1080 1225
1081 template <typename T, size_t inlineCapacity, typename Allocator> 1226 template <typename T, size_t inlineCapacity, typename Allocator>
1082 template <size_t otherCapacity> 1227 template <size_t otherCapacity>
1083 Vector<T, inlineCapacity, Allocator>::Vector( 1228 Vector<T, inlineCapacity, Allocator>::Vector(
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1224 DCHECK(begin()); 1369 DCHECK(begin());
1225 } 1370 }
1226 1371
1227 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize); 1372 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize);
1228 std::fill(begin(), end(), val); 1373 std::fill(begin(), end(), val);
1229 TypeOperations::uninitializedFill(end(), begin() + newSize, val); 1374 TypeOperations::uninitializedFill(end(), begin() + newSize, val);
1230 m_size = newSize; 1375 m_size = newSize;
1231 } 1376 }
1232 1377
1233 template <typename T, size_t inlineCapacity, typename Allocator> 1378 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( 1379 void Vector<T, inlineCapacity, Allocator>::expandCapacity(
1243 size_t newMinCapacity) { 1380 size_t newMinCapacity) {
1244 size_t oldCapacity = capacity(); 1381 size_t oldCapacity = capacity();
1245 size_t expandedCapacity = oldCapacity; 1382 size_t expandedCapacity = oldCapacity;
1246 // We use a more aggressive expansion strategy for Vectors with inline 1383 // 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 1384 // 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 1385 // risk of heap bloat is minimized. Furthermore, exceeding the inline
1249 // capacity limit is not supposed to happen in the common case and may 1386 // capacity limit is not supposed to happen in the common case and may
1250 // indicate a pathological condition or microbenchmark. 1387 // indicate a pathological condition or microbenchmark.
1251 if (INLINE_CAPACITY) { 1388 if (INLINE_CAPACITY) {
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
1400 1537
1401 Base::deallocateBuffer(oldBuffer); 1538 Base::deallocateBuffer(oldBuffer);
1402 } 1539 }
1403 1540
1404 // Templatizing these is better than just letting the conversion happen 1541 // Templatizing these is better than just letting the conversion happen
1405 // implicitly, because for instance it allows a PassRefPtr to be appended to a 1542 // implicitly, because for instance it allows a PassRefPtr to be appended to a
1406 // RefPtr vector without refcount thrash. 1543 // RefPtr vector without refcount thrash.
1407 1544
1408 template <typename T, size_t inlineCapacity, typename Allocator> 1545 template <typename T, size_t inlineCapacity, typename Allocator>
1409 template <typename U> 1546 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) { 1547 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::push_back(U&& val) {
1429 DCHECK(Allocator::isAllocationAllowed()); 1548 DCHECK(Allocator::isAllocationAllowed());
1430 if (LIKELY(size() != capacity())) { 1549 if (LIKELY(size() != capacity())) {
1431 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); 1550 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1);
1432 new (NotNull, end()) T(std::forward<U>(val)); 1551 new (NotNull, end()) T(std::forward<U>(val));
1433 ++m_size; 1552 ++m_size;
1434 return; 1553 return;
1435 } 1554 }
1436 1555
1437 appendSlowCase(std::forward<U>(val)); 1556 appendSlowCase(std::forward<U>(val));
(...skipping 11 matching lines...) Expand all
1449 expandCapacity(size() + 1); 1568 expandCapacity(size() + 1);
1450 1569
1451 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); 1570 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1);
1452 T* t = new (NotNull, end()) T(std::forward<Args>(args)...); 1571 T* t = new (NotNull, end()) T(std::forward<Args>(args)...);
1453 ++m_size; 1572 ++m_size;
1454 return *t; 1573 return *t;
1455 } 1574 }
1456 1575
1457 template <typename T, size_t inlineCapacity, typename Allocator> 1576 template <typename T, size_t inlineCapacity, typename Allocator>
1458 template <typename U> 1577 template <typename U>
1578 void Vector<T, inlineCapacity, Allocator>::append(const U* data,
1579 size_t dataSize) {
1580 DCHECK(Allocator::isAllocationAllowed());
1581 size_t newSize = m_size + dataSize;
1582 if (newSize > capacity()) {
1583 data = expandCapacity(newSize, data);
1584 DCHECK(begin());
1585 }
1586 RELEASE_ASSERT(newSize >= m_size);
1587 T* dest = end();
1588 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize);
1589 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(
1590 data, &data[dataSize], dest);
1591 m_size = newSize;
1592 }
1593
1594 template <typename T, size_t inlineCapacity, typename Allocator>
1595 template <typename U>
1459 NEVER_INLINE void Vector<T, inlineCapacity, Allocator>::appendSlowCase( 1596 NEVER_INLINE void Vector<T, inlineCapacity, Allocator>::appendSlowCase(
1460 U&& val) { 1597 U&& val) {
1461 DCHECK_EQ(size(), capacity()); 1598 DCHECK_EQ(size(), capacity());
1462 1599
1463 typename std::remove_reference<U>::type* ptr = &val; 1600 typename std::remove_reference<U>::type* ptr = &val;
1464 ptr = expandCapacity(size() + 1, ptr); 1601 ptr = expandCapacity(size() + 1, ptr);
1465 DCHECK(begin()); 1602 DCHECK(begin());
1466 1603
1467 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); 1604 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1);
1468 new (NotNull, end()) T(std::forward<U>(*ptr)); 1605 new (NotNull, end()) T(std::forward<U>(*ptr));
1469 ++m_size; 1606 ++m_size;
1470 } 1607 }
1471 1608
1609 template <typename T, size_t inlineCapacity, typename Allocator>
1610 template <typename U, size_t otherCapacity, typename OtherAllocator>
1611 inline void Vector<T, inlineCapacity, Allocator>::appendVector(
1612 const Vector<U, otherCapacity, OtherAllocator>& val) {
1613 append(val.begin(), val.size());
1614 }
1615
1616 template <typename T, size_t inlineCapacity, typename Allocator>
1617 template <typename Iterator>
1618 void Vector<T, inlineCapacity, Allocator>::appendRange(Iterator begin,
1619 Iterator end) {
1620 for (Iterator it = begin; it != end; ++it)
1621 push_back(*it);
1622 }
1623
1472 // This version of append saves a branch in the case where you know that the 1624 // 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. 1625 // vector's capacity is large enough for the append to succeed.
1474
1475 template <typename T, size_t inlineCapacity, typename Allocator> 1626 template <typename T, size_t inlineCapacity, typename Allocator>
1476 template <typename U> 1627 template <typename U>
1477 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::uncheckedAppend( 1628 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::uncheckedAppend(
1478 U&& val) { 1629 U&& val) {
1479 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER 1630 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER
1480 // Vectors in ASAN builds don't have inlineCapacity. 1631 // Vectors in ASAN builds don't have inlineCapacity.
1481 push_back(std::forward<U>(val)); 1632 push_back(std::forward<U>(val));
1482 #else 1633 #else
1483 DCHECK_LT(size(), capacity()); 1634 DCHECK_LT(size(), capacity());
1484 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); 1635 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1);
1485 new (NotNull, end()) T(std::forward<U>(val)); 1636 new (NotNull, end()) T(std::forward<U>(val));
1486 ++m_size; 1637 ++m_size;
1487 #endif 1638 #endif
1488 } 1639 }
1489 1640
1490 template <typename T, size_t inlineCapacity, typename Allocator> 1641 template <typename T, size_t inlineCapacity, typename Allocator>
1491 template <typename U, size_t otherCapacity, typename OtherAllocator> 1642 template <typename U>
1492 inline void Vector<T, inlineCapacity, Allocator>::appendVector( 1643 inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position,
1493 const Vector<U, otherCapacity, OtherAllocator>& val) { 1644 U&& val) {
1494 append(val.begin(), val.size()); 1645 DCHECK(Allocator::isAllocationAllowed());
1646 RELEASE_ASSERT(position <= size());
1647 typename std::remove_reference<U>::type* data = &val;
1648 if (size() == capacity()) {
1649 data = expandCapacity(size() + 1, data);
1650 DCHECK(begin());
1651 }
1652 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1);
1653 T* spot = begin() + position;
1654 TypeOperations::moveOverlapping(spot, end(), spot + 1);
1655 new (NotNull, spot) T(std::forward<U>(*data));
1656 ++m_size;
1495 } 1657 }
1496 1658
1497 template <typename T, size_t inlineCapacity, typename Allocator> 1659 template <typename T, size_t inlineCapacity, typename Allocator>
1498 template <typename U> 1660 template <typename U>
1499 void Vector<T, inlineCapacity, Allocator>::insert(size_t position, 1661 void Vector<T, inlineCapacity, Allocator>::insert(size_t position,
1500 const U* data, 1662 const U* data,
1501 size_t dataSize) { 1663 size_t dataSize) {
1502 DCHECK(Allocator::isAllocationAllowed()); 1664 DCHECK(Allocator::isAllocationAllowed());
1503 RELEASE_ASSERT(position <= size()); 1665 RELEASE_ASSERT(position <= size());
1504 size_t newSize = m_size + dataSize; 1666 size_t newSize = m_size + dataSize;
1505 if (newSize > capacity()) { 1667 if (newSize > capacity()) {
1506 data = expandCapacity(newSize, data); 1668 data = expandCapacity(newSize, data);
1507 DCHECK(begin()); 1669 DCHECK(begin());
1508 } 1670 }
1509 RELEASE_ASSERT(newSize >= m_size); 1671 RELEASE_ASSERT(newSize >= m_size);
1510 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize); 1672 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize);
1511 T* spot = begin() + position; 1673 T* spot = begin() + position;
1512 TypeOperations::moveOverlapping(spot, end(), spot + dataSize); 1674 TypeOperations::moveOverlapping(spot, end(), spot + dataSize);
1513 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy( 1675 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(
1514 data, &data[dataSize], spot); 1676 data, &data[dataSize], spot);
1515 m_size = newSize; 1677 m_size = newSize;
1516 } 1678 }
1517 1679
1518 template <typename T, size_t inlineCapacity, typename Allocator> 1680 template <typename T, size_t inlineCapacity, typename Allocator>
1681 template <typename U, size_t otherCapacity, typename OtherAllocator>
1682 inline void Vector<T, inlineCapacity, Allocator>::insert(
1683 size_t position,
1684 const Vector<U, otherCapacity, OtherAllocator>& val) {
1685 insert(position, val.begin(), val.size());
1686 }
1687
1688 template <typename T, size_t inlineCapacity, typename Allocator>
1519 template <typename U> 1689 template <typename U>
1520 inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, 1690 inline void Vector<T, inlineCapacity, Allocator>::prepend(U&& val) {
1521 U&& val) { 1691 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 } 1692 }
1543 1693
1544 template <typename T, size_t inlineCapacity, typename Allocator> 1694 template <typename T, size_t inlineCapacity, typename Allocator>
1545 template <typename U> 1695 template <typename U>
1546 void Vector<T, inlineCapacity, Allocator>::prepend(const U* data, 1696 void Vector<T, inlineCapacity, Allocator>::prepend(const U* data,
1547 size_t dataSize) { 1697 size_t dataSize) {
1548 insert(0, data, dataSize); 1698 insert(0, data, dataSize);
1549 } 1699 }
1550 1700
1551 template <typename T, size_t inlineCapacity, typename Allocator> 1701 template <typename T, size_t inlineCapacity, typename Allocator>
1552 template <typename U> 1702 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( 1703 inline void Vector<T, inlineCapacity, Allocator>::prependVector(
1560 const Vector<U, c, V>& val) { 1704 const Vector<U, otherCapacity, OtherAllocator>& val) {
1561 insert(0, val.begin(), val.size()); 1705 insert(0, val.begin(), val.size());
1562 } 1706 }
1563 1707
1564 template <typename T, size_t inlineCapacity, typename Allocator> 1708 template <typename T, size_t inlineCapacity, typename Allocator>
1565 inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position) { 1709 inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position) {
1566 RELEASE_ASSERT(position < size()); 1710 RELEASE_ASSERT(position < size());
1567 T* spot = begin() + position; 1711 T* spot = begin() + position;
1568 spot->~T(); 1712 spot->~T();
1569 TypeOperations::moveOverlapping(spot + 1, end(), spot); 1713 TypeOperations::moveOverlapping(spot + 1, end(), spot);
1570 clearUnusedSlots(end() - 1, end()); 1714 clearUnusedSlots(end() - 1, end());
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1649 visitor, *const_cast<T*>(bufferEntry)); 1793 visitor, *const_cast<T*>(bufferEntry));
1650 checkUnusedSlots(buffer() + size(), buffer() + capacity()); 1794 checkUnusedSlots(buffer() + size(), buffer() + capacity());
1651 } 1795 }
1652 } 1796 }
1653 1797
1654 } // namespace WTF 1798 } // namespace WTF
1655 1799
1656 using WTF::Vector; 1800 using WTF::Vector;
1657 1801
1658 #endif // WTF_Vector_h 1802 #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