| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |