| 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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 #endif | 53 #endif |
| 54 | 54 |
| 55 template <typename T, size_t inlineBuffer, typename Allocator> | 55 template <typename T, size_t inlineBuffer, typename Allocator> |
| 56 class Deque; | 56 class Deque; |
| 57 | 57 |
| 58 template <bool needsDestruction, typename T> | 58 template <bool needsDestruction, typename T> |
| 59 struct VectorDestructor; | 59 struct VectorDestructor; |
| 60 | 60 |
| 61 template <typename T> | 61 template <typename T> |
| 62 struct VectorDestructor<false, T> { | 62 struct VectorDestructor<false, T> { |
| 63 static void destruct(T*, T*) {} | 63 static void destruct(T*, T*) {} |
| 64 }; | 64 }; |
| 65 | 65 |
| 66 template <typename T> | 66 template <typename T> |
| 67 struct VectorDestructor<true, T> { | 67 struct VectorDestructor<true, T> { |
| 68 static void destruct(T* begin, T* end) | 68 static void destruct(T* begin, T* end) { |
| 69 { | 69 for (T* cur = begin; cur != end; ++cur) |
| 70 for (T* cur = begin; cur != end; ++cur) | 70 cur->~T(); |
| 71 cur->~T(); | 71 } |
| 72 } | |
| 73 }; | 72 }; |
| 74 | 73 |
| 75 template <bool unusedSlotsMustBeZeroed, typename T> | 74 template <bool unusedSlotsMustBeZeroed, typename T> |
| 76 struct VectorUnusedSlotClearer; | 75 struct VectorUnusedSlotClearer; |
| 77 | 76 |
| 78 template <typename T> | 77 template <typename T> |
| 79 struct VectorUnusedSlotClearer<false, T> { | 78 struct VectorUnusedSlotClearer<false, T> { |
| 80 static void clear(T*, T*) {} | 79 static void clear(T*, T*) {} |
| 81 #if ENABLE(ASSERT) | 80 #if ENABLE(ASSERT) |
| 82 static void checkCleared(const T*, const T*) {} | 81 static void checkCleared(const T*, const T*) {} |
| 83 #endif | 82 #endif |
| 84 }; | 83 }; |
| 85 | 84 |
| 86 template <typename T> | 85 template <typename T> |
| 87 struct VectorUnusedSlotClearer<true, T> { | 86 struct VectorUnusedSlotClearer<true, T> { |
| 88 static void clear(T* begin, T* end) | 87 static void clear(T* begin, T* end) { |
| 89 { | 88 memset(reinterpret_cast<void*>(begin), 0, sizeof(T) * (end - begin)); |
| 90 memset(reinterpret_cast<void*>(begin), 0, sizeof(T) * (end - begin)); | 89 } |
| 91 } | |
| 92 | 90 |
| 93 #if ENABLE(ASSERT) | 91 #if ENABLE(ASSERT) |
| 94 static void checkCleared(const T* begin, const T* end) | 92 static void checkCleared(const T* begin, const T* end) { |
| 95 { | 93 const unsigned char* unusedArea = reinterpret_cast<const unsigned char*>(beg
in); |
| 96 const unsigned char* unusedArea = reinterpret_cast<const unsigned char*>
(begin); | 94 const unsigned char* endAddress = reinterpret_cast<const unsigned char*>(end
); |
| 97 const unsigned char* endAddress = reinterpret_cast<const unsigned char*>
(end); | 95 ASSERT(endAddress >= unusedArea); |
| 98 ASSERT(endAddress >= unusedArea); | 96 for (int i = 0; i < endAddress - unusedArea; ++i) |
| 99 for (int i = 0; i < endAddress - unusedArea; ++i) | 97 ASSERT(!unusedArea[i]); |
| 100 ASSERT(!unusedArea[i]); | 98 } |
| 101 } | |
| 102 #endif | 99 #endif |
| 103 }; | 100 }; |
| 104 | 101 |
| 105 template <bool canInitializeWithMemset, typename T> | 102 template <bool canInitializeWithMemset, typename T> |
| 106 struct VectorInitializer; | 103 struct VectorInitializer; |
| 107 | 104 |
| 108 template <typename T> | 105 template <typename T> |
| 109 struct VectorInitializer<false, T> { | 106 struct VectorInitializer<false, T> { |
| 110 static void initialize(T* begin, T* end) | 107 static void initialize(T* begin, T* end) { |
| 111 { | 108 for (T* cur = begin; cur != end; ++cur) |
| 112 for (T* cur = begin; cur != end; ++cur) | 109 new (NotNull, cur) T; |
| 113 new (NotNull, cur) T; | 110 } |
| 114 } | |
| 115 }; | 111 }; |
| 116 | 112 |
| 117 template <typename T> | 113 template <typename T> |
| 118 struct VectorInitializer<true, T> { | 114 struct VectorInitializer<true, T> { |
| 119 static void initialize(T* begin, T* end) | 115 static void initialize(T* begin, T* end) { |
| 120 { | 116 memset(begin, 0, reinterpret_cast<char*>(end) - reinterpret_cast<char*>(begi
n)); |
| 121 memset(begin, 0, reinterpret_cast<char*>(end) - reinterpret_cast<char*>(
begin)); | 117 } |
| 122 } | |
| 123 }; | 118 }; |
| 124 | 119 |
| 125 template <bool canMoveWithMemcpy, typename T> | 120 template <bool canMoveWithMemcpy, typename T> |
| 126 struct VectorMover; | 121 struct VectorMover; |
| 127 | 122 |
| 128 template <typename T> | 123 template <typename T> |
| 129 struct VectorMover<false, T> { | 124 struct VectorMover<false, T> { |
| 130 static void move(const T* src, const T* srcEnd, T* dst) | 125 static void move(const T* src, const T* srcEnd, T* dst) { |
| 131 { | 126 while (src != srcEnd) { |
| 132 while (src != srcEnd) { | 127 new (NotNull, dst) T(*src); |
| 133 new (NotNull, dst) T(*src); | 128 src->~T(); |
| 134 src->~T(); | 129 ++dst; |
| 135 ++dst; | 130 ++src; |
| 136 ++src; | |
| 137 } | |
| 138 } | 131 } |
| 139 static void moveOverlapping(const T* src, const T* srcEnd, T* dst) | 132 } |
| 140 { | 133 static void moveOverlapping(const T* src, const T* srcEnd, T* dst) { |
| 141 if (src > dst) { | 134 if (src > dst) { |
| 142 move(src, srcEnd, dst); | 135 move(src, srcEnd, dst); |
| 143 } else { | 136 } else { |
| 144 T* dstEnd = dst + (srcEnd - src); | 137 T* dstEnd = dst + (srcEnd - src); |
| 145 while (src != srcEnd) { | 138 while (src != srcEnd) { |
| 146 --srcEnd; | 139 --srcEnd; |
| 147 --dstEnd; | 140 --dstEnd; |
| 148 new (NotNull, dstEnd) T(*srcEnd); | 141 new (NotNull, dstEnd) T(*srcEnd); |
| 149 srcEnd->~T(); | 142 srcEnd->~T(); |
| 150 } | 143 } |
| 151 } | |
| 152 } | 144 } |
| 153 static void swap(T* src, T* srcEnd, T* dst) | 145 } |
| 154 { | 146 static void swap(T* src, T* srcEnd, T* dst) { |
| 155 std::swap_ranges(src, srcEnd, dst); | 147 std::swap_ranges(src, srcEnd, dst); |
| 156 } | 148 } |
| 157 }; | 149 }; |
| 158 | 150 |
| 159 template <typename T> | 151 template <typename T> |
| 160 struct VectorMover<true, T> { | 152 struct VectorMover<true, T> { |
| 161 static void move(const T* src, const T* srcEnd, T* dst) | 153 static void move(const T* src, const T* srcEnd, T* dst) { |
| 162 { | 154 if (LIKELY(dst && src)) |
| 163 if (LIKELY(dst && src)) | 155 memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<
const char*>(src)); |
| 164 memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret
_cast<const char*>(src)); | 156 } |
| 165 } | 157 static void moveOverlapping(const T* src, const T* srcEnd, T* dst) { |
| 166 static void moveOverlapping(const T* src, const T* srcEnd, T* dst) | 158 if (LIKELY(dst && src)) |
| 167 { | 159 memmove(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast
<const char*>(src)); |
| 168 if (LIKELY(dst && src)) | 160 } |
| 169 memmove(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpre
t_cast<const char*>(src)); | 161 static void swap(T* src, T* srcEnd, T* dst) { |
| 170 } | 162 std::swap_ranges(reinterpret_cast<char*>(src), reinterpret_cast<char*>(srcEn
d), reinterpret_cast<char*>(dst)); |
| 171 static void swap(T* src, T* srcEnd, T* dst) | 163 } |
| 172 { | |
| 173 std::swap_ranges(reinterpret_cast<char*>(src), reinterpret_cast<char*>(s
rcEnd), reinterpret_cast<char*>(dst)); | |
| 174 } | |
| 175 }; | 164 }; |
| 176 | 165 |
| 177 template <bool canCopyWithMemcpy, typename T> | 166 template <bool canCopyWithMemcpy, typename T> |
| 178 struct VectorCopier; | 167 struct VectorCopier; |
| 179 | 168 |
| 180 template <typename T> | 169 template <typename T> |
| 181 struct VectorCopier<false, T> { | 170 struct VectorCopier<false, T> { |
| 182 template <typename U> | 171 template <typename U> |
| 183 static void uninitializedCopy(const U* src, const U* srcEnd, T* dst) | 172 static void uninitializedCopy(const U* src, const U* srcEnd, T* dst) { |
| 184 { | 173 while (src != srcEnd) { |
| 185 while (src != srcEnd) { | 174 new (NotNull, dst) T(*src); |
| 186 new (NotNull, dst) T(*src); | 175 ++dst; |
| 187 ++dst; | 176 ++src; |
| 188 ++src; | |
| 189 } | |
| 190 } | 177 } |
| 178 } |
| 191 }; | 179 }; |
| 192 | 180 |
| 193 template <typename T> | 181 template <typename T> |
| 194 struct VectorCopier<true, T> { | 182 struct VectorCopier<true, T> { |
| 195 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst) | 183 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst) { |
| 196 { | 184 if (LIKELY(dst && src)) |
| 197 if (LIKELY(dst && src)) | 185 memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<
const char*>(src)); |
| 198 memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret
_cast<const char*>(src)); | 186 } |
| 199 } | 187 template <typename U> |
| 200 template <typename U> | 188 static void uninitializedCopy(const U* src, const U* srcEnd, T* dst) { |
| 201 static void uninitializedCopy(const U* src, const U* srcEnd, T* dst) | 189 VectorCopier<false, T>::uninitializedCopy(src, srcEnd, dst); |
| 202 { | 190 } |
| 203 VectorCopier<false, T>::uninitializedCopy(src, srcEnd, dst); | |
| 204 } | |
| 205 }; | 191 }; |
| 206 | 192 |
| 207 template <bool canFillWithMemset, typename T> | 193 template <bool canFillWithMemset, typename T> |
| 208 struct VectorFiller; | 194 struct VectorFiller; |
| 209 | 195 |
| 210 template <typename T> | 196 template <typename T> |
| 211 struct VectorFiller<false, T> { | 197 struct VectorFiller<false, T> { |
| 212 static void uninitializedFill(T* dst, T* dstEnd, const T& val) | 198 static void uninitializedFill(T* dst, T* dstEnd, const T& val) { |
| 213 { | 199 while (dst != dstEnd) { |
| 214 while (dst != dstEnd) { | 200 new (NotNull, dst) T(val); |
| 215 new (NotNull, dst) T(val); | 201 ++dst; |
| 216 ++dst; | |
| 217 } | |
| 218 } | 202 } |
| 203 } |
| 219 }; | 204 }; |
| 220 | 205 |
| 221 template <typename T> | 206 template <typename T> |
| 222 struct VectorFiller<true, T> { | 207 struct VectorFiller<true, T> { |
| 223 static void uninitializedFill(T* dst, T* dstEnd, const T& val) | 208 static void uninitializedFill(T* dst, T* dstEnd, const T& val) { |
| 224 { | 209 static_assert(sizeof(T) == sizeof(char), "size of type should be one"); |
| 225 static_assert(sizeof(T) == sizeof(char), "size of type should be one"); | |
| 226 #if COMPILER(GCC) && defined(_FORTIFY_SOURCE) | 210 #if COMPILER(GCC) && defined(_FORTIFY_SOURCE) |
| 227 if (!__builtin_constant_p(dstEnd - dst) || (!(dstEnd - dst))) | 211 if (!__builtin_constant_p(dstEnd - dst) || (!(dstEnd - dst))) |
| 228 memset(dst, val, dstEnd - dst); | 212 memset(dst, val, dstEnd - dst); |
| 229 #else | 213 #else |
| 230 memset(dst, val, dstEnd - dst); | 214 memset(dst, val, dstEnd - dst); |
| 231 #endif | 215 #endif |
| 232 } | 216 } |
| 233 }; | 217 }; |
| 234 | 218 |
| 235 template <bool canCompareWithMemcmp, typename T> | 219 template <bool canCompareWithMemcmp, typename T> |
| 236 struct VectorComparer; | 220 struct VectorComparer; |
| 237 | 221 |
| 238 template <typename T> | 222 template <typename T> |
| 239 struct VectorComparer<false, T> { | 223 struct VectorComparer<false, T> { |
| 240 static bool compare(const T* a, const T* b, size_t size) | 224 static bool compare(const T* a, const T* b, size_t size) { |
| 241 { | 225 ASSERT(a); |
| 242 ASSERT(a); | 226 ASSERT(b); |
| 243 ASSERT(b); | 227 return std::equal(a, a + size, b); |
| 244 return std::equal(a, a + size, b); | 228 } |
| 245 } | |
| 246 }; | 229 }; |
| 247 | 230 |
| 248 template <typename T> | 231 template <typename T> |
| 249 struct VectorComparer<true, T> { | 232 struct VectorComparer<true, T> { |
| 250 static bool compare(const T* a, const T* b, size_t size) | 233 static bool compare(const T* a, const T* b, size_t size) { |
| 251 { | 234 ASSERT(a); |
| 252 ASSERT(a); | 235 ASSERT(b); |
| 253 ASSERT(b); | 236 return memcmp(a, b, sizeof(T) * size) == 0; |
| 254 return memcmp(a, b, sizeof(T) * size) == 0; | 237 } |
| 255 } | |
| 256 }; | 238 }; |
| 257 | 239 |
| 258 template <typename T> | 240 template <typename T> |
| 259 struct VectorTypeOperations { | 241 struct VectorTypeOperations { |
| 260 static void destruct(T* begin, T* end) | 242 static void destruct(T* begin, T* end) { |
| 261 { | 243 VectorDestructor<VectorTraits<T>::needsDestruction, T>::destruct(begin, end)
; |
| 262 VectorDestructor<VectorTraits<T>::needsDestruction, T>::destruct(begin,
end); | 244 } |
| 263 } | |
| 264 | 245 |
| 265 static void initialize(T* begin, T* end) | 246 static void initialize(T* begin, T* end) { |
| 266 { | 247 VectorInitializer<VectorTraits<T>::canInitializeWithMemset, T>::initialize(b
egin, end); |
| 267 VectorInitializer<VectorTraits<T>::canInitializeWithMemset, T>::initiali
ze(begin, end); | 248 } |
| 268 } | |
| 269 | 249 |
| 270 static void move(const T* src, const T* srcEnd, T* dst) | 250 static void move(const T* src, const T* srcEnd, T* dst) { |
| 271 { | 251 VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::move(src, srcEnd, dst); |
| 272 VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::move(src, srcEnd, ds
t); | 252 } |
| 273 } | |
| 274 | 253 |
| 275 static void moveOverlapping(const T* src, const T* srcEnd, T* dst) | 254 static void moveOverlapping(const T* src, const T* srcEnd, T* dst) { |
| 276 { | 255 VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::moveOverlapping(src, src
End, dst); |
| 277 VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::moveOverlapping(src,
srcEnd, dst); | 256 } |
| 278 } | |
| 279 | 257 |
| 280 static void swap(T* src, T* srcEnd, T* dst) | 258 static void swap(T* src, T* srcEnd, T* dst) { |
| 281 { | 259 VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::swap(src, srcEnd, dst); |
| 282 VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::swap(src, srcEnd, ds
t); | 260 } |
| 283 } | |
| 284 | 261 |
| 285 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst) | 262 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst) { |
| 286 { | 263 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(src,
srcEnd, dst); |
| 287 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(s
rc, srcEnd, dst); | 264 } |
| 288 } | |
| 289 | 265 |
| 290 static void uninitializedFill(T* dst, T* dstEnd, const T& val) | 266 static void uninitializedFill(T* dst, T* dstEnd, const T& val) { |
| 291 { | 267 VectorFiller<VectorTraits<T>::canFillWithMemset, T>::uninitializedFill(dst,
dstEnd, val); |
| 292 VectorFiller<VectorTraits<T>::canFillWithMemset, T>::uninitializedFill(d
st, dstEnd, val); | 268 } |
| 293 } | |
| 294 | 269 |
| 295 static bool compare(const T* a, const T* b, size_t size) | 270 static bool compare(const T* a, const T* b, size_t size) { |
| 296 { | 271 return VectorComparer<VectorTraits<T>::canCompareWithMemcmp, T>::compare(a,
b, size); |
| 297 return VectorComparer<VectorTraits<T>::canCompareWithMemcmp, T>::compare
(a, b, size); | 272 } |
| 298 } | |
| 299 }; | 273 }; |
| 300 | 274 |
| 301 template <typename T, bool hasInlineCapacity, typename Allocator> | 275 template <typename T, bool hasInlineCapacity, typename Allocator> |
| 302 class VectorBufferBase { | 276 class VectorBufferBase { |
| 303 WTF_MAKE_NONCOPYABLE(VectorBufferBase); | 277 WTF_MAKE_NONCOPYABLE(VectorBufferBase); |
| 304 public: | |
| 305 void allocateBuffer(size_t newCapacity) | |
| 306 { | |
| 307 ASSERT(newCapacity); | |
| 308 size_t sizeToAllocate = allocationSize(newCapacity); | |
| 309 if (hasInlineCapacity) | |
| 310 m_buffer = Allocator::template allocateInlineVectorBacking<T>(sizeTo
Allocate); | |
| 311 else | |
| 312 m_buffer = Allocator::template allocateVectorBacking<T>(sizeToAlloca
te); | |
| 313 m_capacity = sizeToAllocate / sizeof(T); | |
| 314 } | |
| 315 | 278 |
| 316 void allocateExpandedBuffer(size_t newCapacity) | 279 public: |
| 317 { | 280 void allocateBuffer(size_t newCapacity) { |
| 318 ASSERT(newCapacity); | 281 ASSERT(newCapacity); |
| 319 size_t sizeToAllocate = allocationSize(newCapacity); | 282 size_t sizeToAllocate = allocationSize(newCapacity); |
| 320 if (hasInlineCapacity) | 283 if (hasInlineCapacity) |
| 321 m_buffer = Allocator::template allocateInlineVectorBacking<T>(sizeTo
Allocate); | 284 m_buffer = Allocator::template allocateInlineVectorBacking<T>(sizeToAlloca
te); |
| 322 else | 285 else |
| 323 m_buffer = Allocator::template allocateExpandedVectorBacking<T>(size
ToAllocate); | 286 m_buffer = Allocator::template allocateVectorBacking<T>(sizeToAllocate); |
| 324 m_capacity = sizeToAllocate / sizeof(T); | 287 m_capacity = sizeToAllocate / sizeof(T); |
| 325 } | 288 } |
| 326 | 289 |
| 327 size_t allocationSize(size_t capacity) const | 290 void allocateExpandedBuffer(size_t newCapacity) { |
| 328 { | 291 ASSERT(newCapacity); |
| 329 return Allocator::template quantizedSize<T>(capacity); | 292 size_t sizeToAllocate = allocationSize(newCapacity); |
| 330 } | 293 if (hasInlineCapacity) |
| 294 m_buffer = Allocator::template allocateInlineVectorBacking<T>(sizeToAlloca
te); |
| 295 else |
| 296 m_buffer = Allocator::template allocateExpandedVectorBacking<T>(sizeToAllo
cate); |
| 297 m_capacity = sizeToAllocate / sizeof(T); |
| 298 } |
| 331 | 299 |
| 332 T* buffer() { return m_buffer; } | 300 size_t allocationSize(size_t capacity) const { |
| 333 const T* buffer() const { return m_buffer; } | 301 return Allocator::template quantizedSize<T>(capacity); |
| 334 size_t capacity() const { return m_capacity; } | 302 } |
| 335 | 303 |
| 336 void clearUnusedSlots(T* from, T* to) | 304 T* buffer() { return m_buffer; } |
| 337 { | 305 const T* buffer() const { return m_buffer; } |
| 338 // If the vector backing is garbage-collected and needs tracing or | 306 size_t capacity() const { return m_capacity; } |
| 339 // finalizing, we clear out the unused slots so that the visitor or the | |
| 340 // finalizer does not cause a problem when visiting the unused slots. | |
| 341 VectorUnusedSlotClearer<Allocator::isGarbageCollected && (VectorTraits<T
>::needsDestruction || NeedsTracingTrait<VectorTraits<T>>::value), T>::clear(fro
m, to); | |
| 342 } | |
| 343 | 307 |
| 344 void checkUnusedSlots(const T* from, const T* to) | 308 void clearUnusedSlots(T* from, T* to) { |
| 345 { | 309 // If the vector backing is garbage-collected and needs tracing or |
| 310 // finalizing, we clear out the unused slots so that the visitor or the |
| 311 // finalizer does not cause a problem when visiting the unused slots. |
| 312 VectorUnusedSlotClearer<Allocator::isGarbageCollected && (VectorTraits<T>::n
eedsDestruction || NeedsTracingTrait<VectorTraits<T>>::value), T>::clear(from, t
o); |
| 313 } |
| 314 |
| 315 void checkUnusedSlots(const T* from, const T* to) { |
| 346 #if ENABLE(ASSERT) && !defined(ANNOTATE_CONTIGUOUS_CONTAINER) | 316 #if ENABLE(ASSERT) && !defined(ANNOTATE_CONTIGUOUS_CONTAINER) |
| 347 VectorUnusedSlotClearer<Allocator::isGarbageCollected && (VectorTraits<T
>::needsDestruction || NeedsTracingTrait<VectorTraits<T>>::value), T>::checkClea
red(from, to); | 317 VectorUnusedSlotClearer<Allocator::isGarbageCollected && (VectorTraits<T>::n
eedsDestruction || NeedsTracingTrait<VectorTraits<T>>::value), T>::checkCleared(
from, to); |
| 348 #endif | 318 #endif |
| 349 } | 319 } |
| 350 | 320 |
| 351 protected: | 321 protected: |
| 352 VectorBufferBase() | 322 VectorBufferBase() |
| 353 : m_buffer(nullptr) | 323 : m_buffer(nullptr), m_capacity(0) { |
| 354 , m_capacity(0) | 324 } |
| 355 { | |
| 356 } | |
| 357 | 325 |
| 358 VectorBufferBase(T* buffer, size_t capacity) | 326 VectorBufferBase(T* buffer, size_t capacity) |
| 359 : m_buffer(buffer) | 327 : m_buffer(buffer), m_capacity(capacity) { |
| 360 , m_capacity(capacity) | 328 } |
| 361 { | |
| 362 } | |
| 363 | 329 |
| 364 T* m_buffer; | 330 T* m_buffer; |
| 365 unsigned m_capacity; | 331 unsigned m_capacity; |
| 366 unsigned m_size; | 332 unsigned m_size; |
| 367 }; | 333 }; |
| 368 | 334 |
| 369 template <typename T, size_t inlineCapacity, typename Allocator = PartitionAlloc
ator> | 335 template <typename T, size_t inlineCapacity, typename Allocator = PartitionAlloc
ator> |
| 370 class VectorBuffer; | 336 class VectorBuffer; |
| 371 | 337 |
| 372 template <typename T, typename Allocator> | 338 template <typename T, typename Allocator> |
| 373 class VectorBuffer<T, 0, Allocator> : protected VectorBufferBase<T, false, Alloc
ator> { | 339 class VectorBuffer<T, 0, Allocator> : protected VectorBufferBase<T, false, Alloc
ator> { |
| 374 private: | 340 private: |
| 375 typedef VectorBufferBase<T, false, Allocator> Base; | 341 typedef VectorBufferBase<T, false, Allocator> Base; |
| 376 public: | 342 |
| 377 VectorBuffer() | 343 public: |
| 378 { | 344 VectorBuffer() { |
| 379 } | 345 } |
| 380 | 346 |
| 381 VectorBuffer(size_t capacity) | 347 VectorBuffer(size_t capacity) { |
| 382 { | 348 // Calling malloc(0) might take a lock and may actually do an allocation |
| 383 // Calling malloc(0) might take a lock and may actually do an allocation | 349 // on some systems. |
| 384 // on some systems. | 350 if (capacity) |
| 385 if (capacity) | 351 allocateBuffer(capacity); |
| 386 allocateBuffer(capacity); | 352 } |
| 387 } | 353 |
| 388 | 354 void destruct() { |
| 389 void destruct() | 355 deallocateBuffer(m_buffer); |
| 390 { | 356 m_buffer = nullptr; |
| 391 deallocateBuffer(m_buffer); | 357 } |
| 392 m_buffer = nullptr; | 358 |
| 393 } | 359 void deallocateBuffer(T* bufferToDeallocate) { |
| 394 | 360 Allocator::freeVectorBacking(bufferToDeallocate); |
| 395 void deallocateBuffer(T* bufferToDeallocate) | 361 } |
| 396 { | 362 |
| 397 Allocator::freeVectorBacking(bufferToDeallocate); | 363 bool expandBuffer(size_t newCapacity) { |
| 398 } | 364 size_t sizeToAllocate = allocationSize(newCapacity); |
| 399 | 365 if (Allocator::expandVectorBacking(m_buffer, sizeToAllocate)) { |
| 400 bool expandBuffer(size_t newCapacity) | 366 m_capacity = sizeToAllocate / sizeof(T); |
| 401 { | 367 return true; |
| 402 size_t sizeToAllocate = allocationSize(newCapacity); | 368 } |
| 403 if (Allocator::expandVectorBacking(m_buffer, sizeToAllocate)) { | 369 return false; |
| 404 m_capacity = sizeToAllocate / sizeof(T); | 370 } |
| 405 return true; | 371 |
| 406 } | 372 inline bool shrinkBuffer(size_t newCapacity) { |
| 407 return false; | 373 ASSERT(newCapacity < capacity()); |
| 408 } | 374 size_t sizeToAllocate = allocationSize(newCapacity); |
| 409 | 375 if (Allocator::shrinkVectorBacking(m_buffer, allocationSize(capacity()), siz
eToAllocate)) { |
| 410 inline bool shrinkBuffer(size_t newCapacity) | 376 m_capacity = sizeToAllocate / sizeof(T); |
| 411 { | 377 return true; |
| 412 ASSERT(newCapacity < capacity()); | 378 } |
| 413 size_t sizeToAllocate = allocationSize(newCapacity); | 379 return false; |
| 414 if (Allocator::shrinkVectorBacking(m_buffer, allocationSize(capacity()),
sizeToAllocate)) { | 380 } |
| 415 m_capacity = sizeToAllocate / sizeof(T); | 381 |
| 416 return true; | 382 void resetBufferPointer() { |
| 417 } | 383 m_buffer = nullptr; |
| 418 return false; | 384 m_capacity = 0; |
| 419 } | 385 } |
| 420 | 386 |
| 421 void resetBufferPointer() | 387 void swapVectorBuffer(VectorBuffer<T, 0, Allocator>& other) { |
| 422 { | 388 std::swap(m_buffer, other.m_buffer); |
| 423 m_buffer = nullptr; | 389 std::swap(m_capacity, other.m_capacity); |
| 424 m_capacity = 0; | 390 } |
| 425 } | 391 |
| 426 | 392 using Base::allocateBuffer; |
| 427 void swapVectorBuffer(VectorBuffer<T, 0, Allocator>& other) | 393 using Base::allocationSize; |
| 428 { | 394 |
| 429 std::swap(m_buffer, other.m_buffer); | 395 using Base::buffer; |
| 430 std::swap(m_capacity, other.m_capacity); | 396 using Base::capacity; |
| 431 } | 397 |
| 432 | 398 using Base::clearUnusedSlots; |
| 433 using Base::allocateBuffer; | 399 using Base::checkUnusedSlots; |
| 434 using Base::allocationSize; | 400 |
| 435 | 401 bool hasOutOfLineBuffer() const { |
| 436 using Base::buffer; | 402 // When inlineCapacity is 0 we have an out of line buffer if we have a |
| 437 using Base::capacity; | 403 // buffer. |
| 438 | 404 return buffer(); |
| 439 using Base::clearUnusedSlots; | 405 } |
| 440 using Base::checkUnusedSlots; | 406 |
| 441 | 407 protected: |
| 442 bool hasOutOfLineBuffer() const | 408 using Base::m_size; |
| 443 { | 409 |
| 444 // When inlineCapacity is 0 we have an out of line buffer if we have a | 410 private: |
| 445 // buffer. | 411 using Base::m_buffer; |
| 446 return buffer(); | 412 using Base::m_capacity; |
| 447 } | |
| 448 | |
| 449 protected: | |
| 450 using Base::m_size; | |
| 451 | |
| 452 private: | |
| 453 using Base::m_buffer; | |
| 454 using Base::m_capacity; | |
| 455 }; | 413 }; |
| 456 | 414 |
| 457 template <typename T, size_t inlineCapacity, typename Allocator> | 415 template <typename T, size_t inlineCapacity, typename Allocator> |
| 458 class VectorBuffer : protected VectorBufferBase<T, true, Allocator> { | 416 class VectorBuffer : protected VectorBufferBase<T, true, Allocator> { |
| 459 WTF_MAKE_NONCOPYABLE(VectorBuffer); | 417 WTF_MAKE_NONCOPYABLE(VectorBuffer); |
| 460 typedef VectorBufferBase<T, true, Allocator> Base; | 418 typedef VectorBufferBase<T, true, Allocator> Base; |
| 461 | 419 |
| 462 public: | 420 public: |
| 463 VectorBuffer() | 421 VectorBuffer() |
| 464 : Base(inlineBuffer(), inlineCapacity) | 422 : Base(inlineBuffer(), inlineCapacity) { |
| 465 { | 423 } |
| 466 } | 424 |
| 467 | 425 VectorBuffer(size_t capacity) |
| 468 VectorBuffer(size_t capacity) | 426 : Base(inlineBuffer(), inlineCapacity) { |
| 469 : Base(inlineBuffer(), inlineCapacity) | 427 if (capacity > inlineCapacity) |
| 470 { | 428 Base::allocateBuffer(capacity); |
| 471 if (capacity > inlineCapacity) | 429 } |
| 472 Base::allocateBuffer(capacity); | 430 |
| 473 } | 431 void destruct() { |
| 474 | 432 deallocateBuffer(m_buffer); |
| 475 void destruct() | 433 m_buffer = nullptr; |
| 476 { | 434 } |
| 477 deallocateBuffer(m_buffer); | 435 |
| 478 m_buffer = nullptr; | 436 NEVER_INLINE void reallyDeallocateBuffer(T* bufferToDeallocate) { |
| 479 } | 437 Allocator::freeInlineVectorBacking(bufferToDeallocate); |
| 480 | 438 } |
| 481 NEVER_INLINE void reallyDeallocateBuffer(T* bufferToDeallocate) | 439 |
| 482 { | 440 void deallocateBuffer(T* bufferToDeallocate) { |
| 483 Allocator::freeInlineVectorBacking(bufferToDeallocate); | 441 if (UNLIKELY(bufferToDeallocate != inlineBuffer())) |
| 484 } | 442 reallyDeallocateBuffer(bufferToDeallocate); |
| 485 | 443 } |
| 486 void deallocateBuffer(T* bufferToDeallocate) | 444 |
| 487 { | 445 bool expandBuffer(size_t newCapacity) { |
| 488 if (UNLIKELY(bufferToDeallocate != inlineBuffer())) | 446 ASSERT(newCapacity > inlineCapacity); |
| 489 reallyDeallocateBuffer(bufferToDeallocate); | 447 if (m_buffer == inlineBuffer()) |
| 490 } | 448 return false; |
| 491 | 449 |
| 492 bool expandBuffer(size_t newCapacity) | 450 size_t sizeToAllocate = allocationSize(newCapacity); |
| 493 { | 451 if (Allocator::expandInlineVectorBacking(m_buffer, sizeToAllocate)) { |
| 494 ASSERT(newCapacity > inlineCapacity); | 452 m_capacity = sizeToAllocate / sizeof(T); |
| 495 if (m_buffer == inlineBuffer()) | 453 return true; |
| 496 return false; | 454 } |
| 497 | 455 return false; |
| 498 size_t sizeToAllocate = allocationSize(newCapacity); | 456 } |
| 499 if (Allocator::expandInlineVectorBacking(m_buffer, sizeToAllocate)) { | 457 |
| 500 m_capacity = sizeToAllocate / sizeof(T); | 458 inline bool shrinkBuffer(size_t newCapacity) { |
| 501 return true; | 459 ASSERT(newCapacity < capacity()); |
| 502 } | 460 if (newCapacity <= inlineCapacity) { |
| 503 return false; | 461 // We need to switch to inlineBuffer. Vector::shrinkCapacity will |
| 504 } | 462 // handle it. |
| 505 | 463 return false; |
| 506 inline bool shrinkBuffer(size_t newCapacity) | 464 } |
| 507 { | 465 ASSERT(m_buffer != inlineBuffer()); |
| 508 ASSERT(newCapacity < capacity()); | 466 size_t newSize = allocationSize(newCapacity); |
| 509 if (newCapacity <= inlineCapacity) { | 467 if (!Allocator::shrinkInlineVectorBacking(m_buffer, allocationSize(capacity(
)), newSize)) |
| 510 // We need to switch to inlineBuffer. Vector::shrinkCapacity will | 468 return false; |
| 511 // handle it. | 469 m_capacity = newSize / sizeof(T); |
| 512 return false; | 470 return true; |
| 513 } | 471 } |
| 514 ASSERT(m_buffer != inlineBuffer()); | 472 |
| 515 size_t newSize = allocationSize(newCapacity); | 473 void resetBufferPointer() { |
| 516 if (!Allocator::shrinkInlineVectorBacking(m_buffer, allocationSize(capac
ity()), newSize)) | 474 m_buffer = inlineBuffer(); |
| 517 return false; | 475 m_capacity = inlineCapacity; |
| 518 m_capacity = newSize / sizeof(T); | 476 } |
| 519 return true; | 477 |
| 520 } | 478 void allocateBuffer(size_t newCapacity) { |
| 521 | 479 // FIXME: This should ASSERT(!m_buffer) to catch misuse/leaks. |
| 522 void resetBufferPointer() | 480 if (newCapacity > inlineCapacity) |
| 523 { | 481 Base::allocateBuffer(newCapacity); |
| 524 m_buffer = inlineBuffer(); | 482 else |
| 525 m_capacity = inlineCapacity; | 483 resetBufferPointer(); |
| 526 } | 484 } |
| 527 | 485 |
| 528 void allocateBuffer(size_t newCapacity) | 486 void allocateExpandedBuffer(size_t newCapacity) { |
| 529 { | 487 if (newCapacity > inlineCapacity) |
| 530 // FIXME: This should ASSERT(!m_buffer) to catch misuse/leaks. | 488 Base::allocateExpandedBuffer(newCapacity); |
| 531 if (newCapacity > inlineCapacity) | 489 else |
| 532 Base::allocateBuffer(newCapacity); | 490 resetBufferPointer(); |
| 533 else | 491 } |
| 534 resetBufferPointer(); | 492 |
| 535 } | 493 size_t allocationSize(size_t capacity) const { |
| 536 | 494 if (capacity <= inlineCapacity) |
| 537 void allocateExpandedBuffer(size_t newCapacity) | 495 return m_inlineBufferSize; |
| 538 { | 496 return Base::allocationSize(capacity); |
| 539 if (newCapacity > inlineCapacity) | 497 } |
| 540 Base::allocateExpandedBuffer(newCapacity); | 498 |
| 541 else | 499 void swapVectorBuffer(VectorBuffer<T, inlineCapacity, Allocator>& other) { |
| 542 resetBufferPointer(); | 500 typedef VectorTypeOperations<T> TypeOperations; |
| 543 } | 501 |
| 544 | 502 if (buffer() == inlineBuffer() && other.buffer() == other.inlineBuffer()) { |
| 545 size_t allocationSize(size_t capacity) const | 503 ASSERT(m_capacity == other.m_capacity); |
| 546 { | 504 if (m_size > other.m_size) { |
| 547 if (capacity <= inlineCapacity) | 505 ANNOTATE_CHANGE_SIZE(other.inlineBuffer(), inlineCapacity, other.m_size,
m_size); |
| 548 return m_inlineBufferSize; | 506 TypeOperations::swap(inlineBuffer(), inlineBuffer() + other.m_size, othe
r.inlineBuffer()); |
| 549 return Base::allocationSize(capacity); | 507 TypeOperations::move(inlineBuffer() + other.m_size, inlineBuffer() + m_s
ize, other.inlineBuffer() + other.m_size); |
| 550 } | 508 Base::clearUnusedSlots(inlineBuffer() + other.m_size, inlineBuffer() + m
_size); |
| 551 | 509 ANNOTATE_CHANGE_SIZE(inlineBuffer(), inlineCapacity, m_size, other.m_siz
e); |
| 552 void swapVectorBuffer(VectorBuffer<T, inlineCapacity, Allocator>& other) | 510 } else { |
| 553 { | 511 ANNOTATE_CHANGE_SIZE(inlineBuffer(), inlineCapacity, m_size, other.m_siz
e); |
| 554 typedef VectorTypeOperations<T> TypeOperations; | 512 TypeOperations::swap(inlineBuffer(), inlineBuffer() + m_size, other.inli
neBuffer()); |
| 555 | 513 TypeOperations::move(other.inlineBuffer() + m_size, other.inlineBuffer()
+ other.m_size, inlineBuffer() + m_size); |
| 556 if (buffer() == inlineBuffer() && other.buffer() == other.inlineBuffer()
) { | 514 Base::clearUnusedSlots(other.inlineBuffer() + m_size, other.inlineBuffer
() + other.m_size); |
| 557 ASSERT(m_capacity == other.m_capacity); | 515 ANNOTATE_CHANGE_SIZE(other.inlineBuffer(), inlineCapacity, other.m_size,
m_size); |
| 558 if (m_size > other.m_size) { | 516 } |
| 559 ANNOTATE_CHANGE_SIZE(other.inlineBuffer(), inlineCapacity, other
.m_size, m_size); | 517 } else if (buffer() == inlineBuffer()) { |
| 560 TypeOperations::swap(inlineBuffer(), inlineBuffer() + other.m_si
ze, other.inlineBuffer()); | 518 ANNOTATE_DELETE_BUFFER(m_buffer, inlineCapacity, m_size); |
| 561 TypeOperations::move(inlineBuffer() + other.m_size, inlineBuffer
() + m_size, other.inlineBuffer() + other.m_size); | 519 m_buffer = other.m_buffer; |
| 562 Base::clearUnusedSlots(inlineBuffer() + other.m_size, inlineBuff
er() + m_size); | 520 other.m_buffer = other.inlineBuffer(); |
| 563 ANNOTATE_CHANGE_SIZE(inlineBuffer(), inlineCapacity, m_size, oth
er.m_size); | 521 ANNOTATE_NEW_BUFFER(other.m_buffer, inlineCapacity, m_size); |
| 564 } else { | 522 TypeOperations::move(inlineBuffer(), inlineBuffer() + m_size, other.inline
Buffer()); |
| 565 ANNOTATE_CHANGE_SIZE(inlineBuffer(), inlineCapacity, m_size, oth
er.m_size); | 523 Base::clearUnusedSlots(inlineBuffer(), inlineBuffer() + m_size); |
| 566 TypeOperations::swap(inlineBuffer(), inlineBuffer() + m_size, ot
her.inlineBuffer()); | 524 std::swap(m_capacity, other.m_capacity); |
| 567 TypeOperations::move(other.inlineBuffer() + m_size, other.inline
Buffer() + other.m_size, inlineBuffer() + m_size); | 525 } else if (other.buffer() == other.inlineBuffer()) { |
| 568 Base::clearUnusedSlots(other.inlineBuffer() + m_size, other.inli
neBuffer() + other.m_size); | 526 ANNOTATE_DELETE_BUFFER(other.m_buffer, inlineCapacity, other.m_size); |
| 569 ANNOTATE_CHANGE_SIZE(other.inlineBuffer(), inlineCapacity, other
.m_size, m_size); | 527 other.m_buffer = m_buffer; |
| 570 } | 528 m_buffer = inlineBuffer(); |
| 571 } else if (buffer() == inlineBuffer()) { | 529 ANNOTATE_NEW_BUFFER(m_buffer, inlineCapacity, other.m_size); |
| 572 ANNOTATE_DELETE_BUFFER(m_buffer, inlineCapacity, m_size); | 530 TypeOperations::move(other.inlineBuffer(), other.inlineBuffer() + other.m_
size, inlineBuffer()); |
| 573 m_buffer = other.m_buffer; | 531 Base::clearUnusedSlots(other.inlineBuffer(), other.inlineBuffer() + other.
m_size); |
| 574 other.m_buffer = other.inlineBuffer(); | 532 std::swap(m_capacity, other.m_capacity); |
| 575 ANNOTATE_NEW_BUFFER(other.m_buffer, inlineCapacity, m_size); | 533 } else { |
| 576 TypeOperations::move(inlineBuffer(), inlineBuffer() + m_size, other.
inlineBuffer()); | 534 std::swap(m_buffer, other.m_buffer); |
| 577 Base::clearUnusedSlots(inlineBuffer(), inlineBuffer() + m_size); | 535 std::swap(m_capacity, other.m_capacity); |
| 578 std::swap(m_capacity, other.m_capacity); | 536 } |
| 579 } else if (other.buffer() == other.inlineBuffer()) { | 537 } |
| 580 ANNOTATE_DELETE_BUFFER(other.m_buffer, inlineCapacity, other.m_size)
; | 538 |
| 581 other.m_buffer = m_buffer; | 539 using Base::buffer; |
| 582 m_buffer = inlineBuffer(); | 540 using Base::capacity; |
| 583 ANNOTATE_NEW_BUFFER(m_buffer, inlineCapacity, other.m_size); | 541 |
| 584 TypeOperations::move(other.inlineBuffer(), other.inlineBuffer() + ot
her.m_size, inlineBuffer()); | 542 bool hasOutOfLineBuffer() const { |
| 585 Base::clearUnusedSlots(other.inlineBuffer(), other.inlineBuffer() +
other.m_size); | 543 return buffer() && buffer() != inlineBuffer(); |
| 586 std::swap(m_capacity, other.m_capacity); | 544 } |
| 587 } else { | 545 |
| 588 std::swap(m_buffer, other.m_buffer); | 546 protected: |
| 589 std::swap(m_capacity, other.m_capacity); | 547 using Base::m_size; |
| 590 } | 548 |
| 591 } | 549 private: |
| 592 | 550 using Base::m_buffer; |
| 593 using Base::buffer; | 551 using Base::m_capacity; |
| 594 using Base::capacity; | 552 |
| 595 | 553 static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T); |
| 596 bool hasOutOfLineBuffer() const | 554 T* inlineBuffer() { return reinterpret_cast_ptr<T*>(m_inlineBuffer.buffer); } |
| 597 { | 555 const T* inlineBuffer() const { return reinterpret_cast_ptr<const T*>(m_inline
Buffer.buffer); } |
| 598 return buffer() && buffer() != inlineBuffer(); | 556 |
| 599 } | 557 AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer; |
| 600 | 558 template <typename U, size_t inlineBuffer, typename V> |
| 601 protected: | 559 friend class Deque; |
| 602 using Base::m_size; | |
| 603 | |
| 604 private: | |
| 605 using Base::m_buffer; | |
| 606 using Base::m_capacity; | |
| 607 | |
| 608 static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T); | |
| 609 T* inlineBuffer() { return reinterpret_cast_ptr<T*>(m_inlineBuffer.buffer);
} | |
| 610 const T* inlineBuffer() const { return reinterpret_cast_ptr<const T*>(m_inli
neBuffer.buffer); } | |
| 611 | |
| 612 AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer; | |
| 613 template <typename U, size_t inlineBuffer, typename V> | |
| 614 friend class Deque; | |
| 615 }; | 560 }; |
| 616 | 561 |
| 617 template <typename T, size_t inlineCapacity = 0, typename Allocator = PartitionA
llocator> // Heap-allocated vectors with no inlineCapacity never need a destruct
or. | 562 template <typename T, size_t inlineCapacity = 0, typename Allocator = PartitionA
llocator> // Heap-allocated vectors with no inlineCapacity never need a destruc
tor. |
| 618 class Vector : private VectorBuffer<T, INLINE_CAPACITY, Allocator>, public Condi
tionalDestructor<Vector<T, INLINE_CAPACITY, Allocator>, (INLINE_CAPACITY == 0) &
& Allocator::isGarbageCollected> { | 563 class Vector : private VectorBuffer<T, INLINE_CAPACITY, Allocator>, public Condi
tionalDestructor<Vector<T, INLINE_CAPACITY, Allocator>, (INLINE_CAPACITY == 0) &
& Allocator::isGarbageCollected> { |
| 619 WTF_USE_ALLOCATOR(Vector, Allocator); | 564 WTF_USE_ALLOCATOR(Vector, Allocator); |
| 620 typedef VectorBuffer<T, INLINE_CAPACITY, Allocator> Base; | 565 typedef VectorBuffer<T, INLINE_CAPACITY, Allocator> Base; |
| 621 typedef VectorTypeOperations<T> TypeOperations; | 566 typedef VectorTypeOperations<T> TypeOperations; |
| 622 | 567 |
| 623 public: | 568 public: |
| 624 typedef T ValueType; | 569 typedef T ValueType; |
| 625 typedef T value_type; | 570 typedef T value_type; |
| 626 | 571 |
| 627 typedef T* iterator; | 572 typedef T* iterator; |
| 628 typedef const T* const_iterator; | 573 typedef const T* const_iterator; |
| 629 typedef std::reverse_iterator<iterator> reverse_iterator; | 574 typedef std::reverse_iterator<iterator> reverse_iterator; |
| 630 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; | 575 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; |
| 631 | 576 |
| 632 Vector() | 577 Vector() { |
| 633 { | 578 static_assert(!IsPolymorphic<T>::value || !VectorTraits<T>::canInitializeWit
hMemset, "Cannot initialize with memset if there is a vtable"); |
| 634 static_assert(!IsPolymorphic<T>::value || !VectorTraits<T>::canInitializ
eWithMemset, "Cannot initialize with memset if there is a vtable"); | |
| 635 #if ENABLE(OILPAN) | 579 #if ENABLE(OILPAN) |
| 636 static_assert(Allocator::isGarbageCollected || !AllowsOnlyPlacementNew<T
>::value || !NeedsTracing<T>::value, "Cannot put DISALLOW_NEW_EXCEPT_PLACEMENT_N
EW objects that have trace methods into an off-heap Vector"); | 580 static_assert(Allocator::isGarbageCollected || !AllowsOnlyPlacementNew<T>::v
alue || !NeedsTracing<T>::value, "Cannot put DISALLOW_NEW_EXCEPT_PLACEMENT_NEW o
bjects that have trace methods into an off-heap Vector"); |
| 637 #endif | 581 #endif |
| 638 static_assert(Allocator::isGarbageCollected || !IsPointerToGarbageCollec
tedType<T>::value, "Cannot put raw pointers to garbage-collected classes into an
off-heap Vector. Use HeapVector<Member<T>> instead."); | 582 static_assert(Allocator::isGarbageCollected || !IsPointerToGarbageCollectedT
ype<T>::value, "Cannot put raw pointers to garbage-collected classes into an off
-heap Vector. Use HeapVector<Member<T>> instead."); |
| 639 | 583 |
| 640 ANNOTATE_NEW_BUFFER(begin(), capacity(), 0); | 584 ANNOTATE_NEW_BUFFER(begin(), capacity(), 0); |
| 641 m_size = 0; | 585 m_size = 0; |
| 642 } | 586 } |
| 643 | 587 |
| 644 explicit Vector(size_t size) | 588 explicit Vector(size_t size) |
| 645 : Base(size) | 589 : Base(size) { |
| 646 { | 590 static_assert(!IsPolymorphic<T>::value || !VectorTraits<T>::canInitializeWit
hMemset, "Cannot initialize with memset if there is a vtable"); |
| 647 static_assert(!IsPolymorphic<T>::value || !VectorTraits<T>::canInitializ
eWithMemset, "Cannot initialize with memset if there is a vtable"); | |
| 648 #if ENABLE(OILPAN) | 591 #if ENABLE(OILPAN) |
| 649 static_assert(Allocator::isGarbageCollected || !AllowsOnlyPlacementNew<T
>::value || !NeedsTracing<T>::value, "Cannot put DISALLOW_NEW_EXCEPT_PLACEMENT_N
EW objects that have trace methods into an off-heap Vector"); | 592 static_assert(Allocator::isGarbageCollected || !AllowsOnlyPlacementNew<T>::v
alue || !NeedsTracing<T>::value, "Cannot put DISALLOW_NEW_EXCEPT_PLACEMENT_NEW o
bjects that have trace methods into an off-heap Vector"); |
| 650 #endif | 593 #endif |
| 651 static_assert(Allocator::isGarbageCollected || !IsPointerToGarbageCollec
tedType<T>::value, "Cannot put raw pointers to garbage-collected classes into an
off-heap Vector. Use HeapVector<Member<T>> instead."); | 594 static_assert(Allocator::isGarbageCollected || !IsPointerToGarbageCollectedT
ype<T>::value, "Cannot put raw pointers to garbage-collected classes into an off
-heap Vector. Use HeapVector<Member<T>> instead."); |
| 652 | 595 |
| 653 ANNOTATE_NEW_BUFFER(begin(), capacity(), size); | 596 ANNOTATE_NEW_BUFFER(begin(), capacity(), size); |
| 654 m_size = size; | 597 m_size = size; |
| 655 TypeOperations::initialize(begin(), end()); | 598 TypeOperations::initialize(begin(), end()); |
| 656 } | 599 } |
| 657 | 600 |
| 658 // Off-GC-heap vectors: Destructor should be called. | 601 // Off-GC-heap vectors: Destructor should be called. |
| 659 // On-GC-heap vectors: Destructor should be called for inline buffers (if | 602 // On-GC-heap vectors: Destructor should be called for inline buffers (if |
| 660 // any) but destructor shouldn't be called for vector backing since it is | 603 // any) but destructor shouldn't be called for vector backing since it is |
| 661 // managed by the traced GC heap. | 604 // managed by the traced GC heap. |
| 662 void finalize() | 605 void finalize() { |
| 663 { | 606 if (!INLINE_CAPACITY) { |
| 664 if (!INLINE_CAPACITY) { | 607 if (LIKELY(!Base::buffer())) |
| 665 if (LIKELY(!Base::buffer())) | 608 return; |
| 666 return; | 609 } |
| 667 } | 610 ANNOTATE_DELETE_BUFFER(begin(), capacity(), m_size); |
| 668 ANNOTATE_DELETE_BUFFER(begin(), capacity(), m_size); | 611 if (LIKELY(m_size) && !(Allocator::isGarbageCollected && this->hasOutOfLineB
uffer())) { |
| 669 if (LIKELY(m_size) && !(Allocator::isGarbageCollected && this->hasOutOfL
ineBuffer())) { | 612 TypeOperations::destruct(begin(), end()); |
| 670 TypeOperations::destruct(begin(), end()); | 613 m_size = 0; // Partial protection against use-after-free. |
| 671 m_size = 0; // Partial protection against use-after-free. | 614 } |
| 672 } | 615 |
| 673 | 616 Base::destruct(); |
| 674 Base::destruct(); | 617 } |
| 675 } | 618 |
| 676 | 619 void finalizeGarbageCollectedObject() { |
| 677 void finalizeGarbageCollectedObject() | 620 finalize(); |
| 678 { | 621 } |
| 679 finalize(); | 622 |
| 680 } | 623 Vector(const Vector&); |
| 681 | 624 template <size_t otherCapacity> |
| 682 Vector(const Vector&); | 625 explicit Vector(const Vector<T, otherCapacity, Allocator>&); |
| 683 template <size_t otherCapacity> | 626 |
| 684 explicit Vector(const Vector<T, otherCapacity, Allocator>&); | 627 Vector& operator=(const Vector&); |
| 685 | 628 template <size_t otherCapacity> |
| 686 Vector& operator=(const Vector&); | 629 Vector& operator=(const Vector<T, otherCapacity, Allocator>&); |
| 687 template <size_t otherCapacity> | 630 |
| 688 Vector& operator=(const Vector<T, otherCapacity, Allocator>&); | 631 Vector(Vector&&); |
| 689 | 632 Vector& operator=(Vector&&); |
| 690 Vector(Vector&&); | 633 |
| 691 Vector& operator=(Vector&&); | 634 size_t size() const { return m_size; } |
| 692 | 635 size_t capacity() const { return Base::capacity(); } |
| 693 size_t size() const { return m_size; } | 636 bool isEmpty() const { return !size(); } |
| 694 size_t capacity() const { return Base::capacity(); } | 637 |
| 695 bool isEmpty() const { return !size(); } | 638 T& at(size_t i) { |
| 696 | 639 RELEASE_ASSERT(i < size()); |
| 697 T& at(size_t i) | 640 return Base::buffer()[i]; |
| 698 { | 641 } |
| 699 RELEASE_ASSERT(i < size()); | 642 const T& at(size_t i) const { |
| 700 return Base::buffer()[i]; | 643 RELEASE_ASSERT(i < size()); |
| 701 } | 644 return Base::buffer()[i]; |
| 702 const T& at(size_t i) const | 645 } |
| 703 { | 646 |
| 704 RELEASE_ASSERT(i < size()); | 647 T& operator[](size_t i) { return at(i); } |
| 705 return Base::buffer()[i]; | 648 const T& operator[](size_t i) const { return at(i); } |
| 706 } | 649 |
| 707 | 650 T* data() { return Base::buffer(); } |
| 708 T& operator[](size_t i) { return at(i); } | 651 const T* data() const { return Base::buffer(); } |
| 709 const T& operator[](size_t i) const { return at(i); } | 652 |
| 710 | 653 iterator begin() { return data(); } |
| 711 T* data() { return Base::buffer(); } | 654 iterator end() { return begin() + m_size; } |
| 712 const T* data() const { return Base::buffer(); } | 655 const_iterator begin() const { return data(); } |
| 713 | 656 const_iterator end() const { return begin() + m_size; } |
| 714 iterator begin() { return data(); } | 657 |
| 715 iterator end() { return begin() + m_size; } | 658 reverse_iterator rbegin() { return reverse_iterator(end()); } |
| 716 const_iterator begin() const { return data(); } | 659 reverse_iterator rend() { return reverse_iterator(begin()); } |
| 717 const_iterator end() const { return begin() + m_size; } | 660 const_reverse_iterator rbegin() const { return const_reverse_iterator(end());
} |
| 718 | 661 const_reverse_iterator rend() const { return const_reverse_iterator(begin());
} |
| 719 reverse_iterator rbegin() { return reverse_iterator(end()); } | 662 |
| 720 reverse_iterator rend() { return reverse_iterator(begin()); } | 663 T& first() { return at(0); } |
| 721 const_reverse_iterator rbegin() const { return const_reverse_iterator(end())
; } | 664 const T& first() const { return at(0); } |
| 722 const_reverse_iterator rend() const { return const_reverse_iterator(begin())
; } | 665 T& last() { return at(size() - 1); } |
| 723 | 666 const T& last() const { return at(size() - 1); } |
| 724 T& first() { return at(0); } | 667 |
| 725 const T& first() const { return at(0); } | 668 template <typename U> |
| 726 T& last() { return at(size() - 1); } | 669 bool contains(const U&) const; |
| 727 const T& last() const { return at(size() - 1); } | 670 template <typename U> |
| 728 | 671 size_t find(const U&) const; |
| 729 template <typename U> bool contains(const U&) const; | 672 template <typename U> |
| 730 template <typename U> size_t find(const U&) const; | 673 size_t reverseFind(const U&) const; |
| 731 template <typename U> size_t reverseFind(const U&) const; | 674 |
| 732 | 675 void shrink(size_t); |
| 733 void shrink(size_t); | 676 void grow(size_t); |
| 734 void grow(size_t); | 677 void resize(size_t); |
| 735 void resize(size_t); | 678 void reserveCapacity(size_t newCapacity); |
| 736 void reserveCapacity(size_t newCapacity); | 679 void reserveInitialCapacity(size_t initialCapacity); |
| 737 void reserveInitialCapacity(size_t initialCapacity); | 680 void shrinkToFit() { shrinkCapacity(size()); } |
| 738 void shrinkToFit() { shrinkCapacity(size()); } | 681 void shrinkToReasonableCapacity() { |
| 739 void shrinkToReasonableCapacity() | 682 if (size() * 2 < capacity()) |
| 740 { | 683 shrinkCapacity(size() + size() / 4 + 1); |
| 741 if (size() * 2 < capacity()) | 684 } |
| 742 shrinkCapacity(size() + size() / 4 + 1); | 685 |
| 743 } | 686 void clear() { shrinkCapacity(0); } |
| 744 | 687 |
| 745 void clear() { shrinkCapacity(0); } | 688 template <typename U> |
| 746 | 689 void append(const U*, size_t); |
| 747 template <typename U> void append(const U*, size_t); | 690 template <typename U> |
| 748 template <typename U> void append(const U&); | 691 void append(const U&); |
| 749 template <typename U> void uncheckedAppend(const U& val); | 692 template <typename U> |
| 750 template <typename U, size_t otherCapacity, typename V> void appendVector(co
nst Vector<U, otherCapacity, V>&); | 693 void uncheckedAppend(const U& val); |
| 751 | 694 template <typename U, size_t otherCapacity, typename V> |
| 752 template <typename U> void insert(size_t position, const U*, size_t); | 695 void appendVector(const Vector<U, otherCapacity, V>&); |
| 753 template <typename U> void insert(size_t position, const U&); | 696 |
| 754 template <typename U, size_t c, typename V> void insert(size_t position, con
st Vector<U, c, V>&); | 697 template <typename U> |
| 755 | 698 void insert(size_t position, const U*, size_t); |
| 756 template <typename U> void prepend(const U*, size_t); | 699 template <typename U> |
| 757 template <typename U> void prepend(const U&); | 700 void insert(size_t position, const U&); |
| 758 template <typename U, size_t c, typename V> void prepend(const Vector<U, c,
V>&); | 701 template <typename U, size_t c, typename V> |
| 759 | 702 void insert(size_t position, const Vector<U, c, V>&); |
| 760 void remove(size_t position); | 703 |
| 761 void remove(size_t position, size_t length); | 704 template <typename U> |
| 762 | 705 void prepend(const U*, size_t); |
| 763 void removeLast() | 706 template <typename U> |
| 764 { | 707 void prepend(const U&); |
| 765 ASSERT(!isEmpty()); | 708 template <typename U, size_t c, typename V> |
| 766 shrink(size() - 1); | 709 void prepend(const Vector<U, c, V>&); |
| 767 } | 710 |
| 768 | 711 void remove(size_t position); |
| 769 Vector(size_t size, const T& val) | 712 void remove(size_t position, size_t length); |
| 770 : Base(size) | 713 |
| 771 { | 714 void removeLast() { |
| 772 ANNOTATE_NEW_BUFFER(begin(), capacity(), size); | 715 ASSERT(!isEmpty()); |
| 773 m_size = size; | 716 shrink(size() - 1); |
| 774 TypeOperations::uninitializedFill(begin(), end(), val); | 717 } |
| 775 } | 718 |
| 776 | 719 Vector(size_t size, const T& val) |
| 777 void fill(const T&, size_t); | 720 : Base(size) { |
| 778 void fill(const T& val) { fill(val, size()); } | 721 ANNOTATE_NEW_BUFFER(begin(), capacity(), size); |
| 779 | 722 m_size = size; |
| 780 template <typename Iterator> void appendRange(Iterator start, Iterator end); | 723 TypeOperations::uninitializedFill(begin(), end(), val); |
| 781 | 724 } |
| 782 void swap(Vector& other) | 725 |
| 783 { | 726 void fill(const T&, size_t); |
| 784 Base::swapVectorBuffer(other); | 727 void fill(const T& val) { fill(val, size()); } |
| 785 std::swap(m_size, other.m_size); | 728 |
| 786 } | 729 template <typename Iterator> |
| 787 | 730 void appendRange(Iterator start, Iterator end); |
| 788 void reverse(); | 731 |
| 789 | 732 void swap(Vector& other) { |
| 790 template <typename VisitorDispatcher> void trace(VisitorDispatcher); | 733 Base::swapVectorBuffer(other); |
| 791 | 734 std::swap(m_size, other.m_size); |
| 792 protected: | 735 } |
| 793 using Base::checkUnusedSlots; | 736 |
| 794 using Base::clearUnusedSlots; | 737 void reverse(); |
| 795 | 738 |
| 796 private: | 739 template <typename VisitorDispatcher> |
| 797 void expandCapacity(size_t newMinCapacity); | 740 void trace(VisitorDispatcher); |
| 798 const T* expandCapacity(size_t newMinCapacity, const T*); | 741 |
| 799 template <typename U> U* expandCapacity(size_t newMinCapacity, U*); | 742 protected: |
| 800 void shrinkCapacity(size_t newCapacity); | 743 using Base::checkUnusedSlots; |
| 801 template <typename U> void appendSlowCase(const U&); | 744 using Base::clearUnusedSlots; |
| 802 | 745 |
| 803 using Base::m_size; | 746 private: |
| 804 using Base::buffer; | 747 void expandCapacity(size_t newMinCapacity); |
| 805 using Base::capacity; | 748 const T* expandCapacity(size_t newMinCapacity, const T*); |
| 806 using Base::swapVectorBuffer; | 749 template <typename U> |
| 807 using Base::allocateBuffer; | 750 U* expandCapacity(size_t newMinCapacity, U*); |
| 808 using Base::allocationSize; | 751 void shrinkCapacity(size_t newCapacity); |
| 752 template <typename U> |
| 753 void appendSlowCase(const U&); |
| 754 |
| 755 using Base::m_size; |
| 756 using Base::buffer; |
| 757 using Base::capacity; |
| 758 using Base::swapVectorBuffer; |
| 759 using Base::allocateBuffer; |
| 760 using Base::allocationSize; |
| 809 }; | 761 }; |
| 810 | 762 |
| 811 template <typename T, size_t inlineCapacity, typename Allocator> | 763 template <typename T, size_t inlineCapacity, typename Allocator> |
| 812 Vector<T, inlineCapacity, Allocator>::Vector(const Vector& other) | 764 Vector<T, inlineCapacity, Allocator>::Vector(const Vector& other) |
| 813 : Base(other.capacity()) | 765 : Base(other.capacity()) { |
| 814 { | 766 ANNOTATE_NEW_BUFFER(begin(), capacity(), other.size()); |
| 815 ANNOTATE_NEW_BUFFER(begin(), capacity(), other.size()); | 767 m_size = other.size(); |
| 816 m_size = other.size(); | 768 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); |
| 817 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); | |
| 818 } | 769 } |
| 819 | 770 |
| 820 template <typename T, size_t inlineCapacity, typename Allocator> | 771 template <typename T, size_t inlineCapacity, typename Allocator> |
| 821 template <size_t otherCapacity> | 772 template <size_t otherCapacity> |
| 822 Vector<T, inlineCapacity, Allocator>::Vector(const Vector<T, otherCapacity, Allo
cator>& other) | 773 Vector<T, inlineCapacity, Allocator>::Vector(const Vector<T, otherCapacity, Allo
cator>& other) |
| 823 : Base(other.capacity()) | 774 : Base(other.capacity()) { |
| 824 { | 775 ANNOTATE_NEW_BUFFER(begin(), capacity(), other.size()); |
| 825 ANNOTATE_NEW_BUFFER(begin(), capacity(), other.size()); | 776 m_size = other.size(); |
| 826 m_size = other.size(); | 777 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); |
| 827 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); | 778 } |
| 828 } | 779 |
| 829 | 780 template <typename T, size_t inlineCapacity, typename Allocator> |
| 830 template <typename T, size_t inlineCapacity, typename Allocator> | 781 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>::oper
ator=(const Vector<T, inlineCapacity, Allocator>& other) { |
| 831 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>::oper
ator=(const Vector<T, inlineCapacity, Allocator>& other) | 782 if (UNLIKELY(&other == this)) |
| 832 { | |
| 833 if (UNLIKELY(&other == this)) | |
| 834 return *this; | |
| 835 | |
| 836 if (size() > other.size()) { | |
| 837 shrink(other.size()); | |
| 838 } else if (other.size() > capacity()) { | |
| 839 clear(); | |
| 840 reserveCapacity(other.size()); | |
| 841 ASSERT(begin()); | |
| 842 } | |
| 843 | |
| 844 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, other.size()); | |
| 845 std::copy(other.begin(), other.begin() + size(), begin()); | |
| 846 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end()
); | |
| 847 m_size = other.size(); | |
| 848 | |
| 849 return *this; | 783 return *this; |
| 850 } | 784 |
| 851 | 785 if (size() > other.size()) { |
| 852 inline bool typelessPointersAreEqual(const void* a, const void* b) { return a ==
b; } | 786 shrink(other.size()); |
| 787 } else if (other.size() > capacity()) { |
| 788 clear(); |
| 789 reserveCapacity(other.size()); |
| 790 ASSERT(begin()); |
| 791 } |
| 792 |
| 793 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, other.size()); |
| 794 std::copy(other.begin(), other.begin() + size(), begin()); |
| 795 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end()); |
| 796 m_size = other.size(); |
| 797 |
| 798 return *this; |
| 799 } |
| 800 |
| 801 inline bool typelessPointersAreEqual(const void* a, const void* b) { |
| 802 return a == b; |
| 803 } |
| 853 | 804 |
| 854 template <typename T, size_t inlineCapacity, typename Allocator> | 805 template <typename T, size_t inlineCapacity, typename Allocator> |
| 855 template <size_t otherCapacity> | 806 template <size_t otherCapacity> |
| 856 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>::oper
ator=(const Vector<T, otherCapacity, Allocator>& other) | 807 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>::oper
ator=(const Vector<T, otherCapacity, Allocator>& other) { |
| 857 { | 808 // If the inline capacities match, we should call the more specific |
| 858 // If the inline capacities match, we should call the more specific | 809 // template. If the inline capacities don't match, the two objects |
| 859 // template. If the inline capacities don't match, the two objects | 810 // shouldn't be allocated the same address. |
| 860 // shouldn't be allocated the same address. | 811 ASSERT(!typelessPointersAreEqual(&other, this)); |
| 861 ASSERT(!typelessPointersAreEqual(&other, this)); | 812 |
| 862 | 813 if (size() > other.size()) { |
| 863 if (size() > other.size()) { | 814 shrink(other.size()); |
| 864 shrink(other.size()); | 815 } else if (other.size() > capacity()) { |
| 865 } else if (other.size() > capacity()) { | 816 clear(); |
| 866 clear(); | 817 reserveCapacity(other.size()); |
| 867 reserveCapacity(other.size()); | 818 ASSERT(begin()); |
| 868 ASSERT(begin()); | 819 } |
| 869 } | 820 |
| 870 | 821 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, other.size()); |
| 871 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, other.size()); | 822 std::copy(other.begin(), other.begin() + size(), begin()); |
| 872 std::copy(other.begin(), other.begin() + size(), begin()); | 823 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end()); |
| 873 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end()
); | 824 m_size = other.size(); |
| 874 m_size = other.size(); | 825 |
| 875 | 826 return *this; |
| 876 return *this; | 827 } |
| 877 } | 828 |
| 878 | 829 template <typename T, size_t inlineCapacity, typename Allocator> |
| 879 template <typename T, size_t inlineCapacity, typename Allocator> | 830 Vector<T, inlineCapacity, Allocator>::Vector(Vector<T, inlineCapacity, Allocator
>&& other) { |
| 880 Vector<T, inlineCapacity, Allocator>::Vector(Vector<T, inlineCapacity, Allocator
>&& other) | 831 m_size = 0; |
| 881 { | 832 // It's a little weird to implement a move constructor using swap but this |
| 882 m_size = 0; | 833 // way we don't have to add a move constructor to VectorBuffer. |
| 883 // It's a little weird to implement a move constructor using swap but this | 834 swap(other); |
| 884 // way we don't have to add a move constructor to VectorBuffer. | 835 } |
| 885 swap(other); | 836 |
| 886 } | 837 template <typename T, size_t inlineCapacity, typename Allocator> |
| 887 | 838 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>::oper
ator=(Vector<T, inlineCapacity, Allocator>&& other) { |
| 888 template <typename T, size_t inlineCapacity, typename Allocator> | 839 swap(other); |
| 889 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>::oper
ator=(Vector<T, inlineCapacity, Allocator>&& other) | 840 return *this; |
| 890 { | |
| 891 swap(other); | |
| 892 return *this; | |
| 893 } | 841 } |
| 894 | 842 |
| 895 template <typename T, size_t inlineCapacity, typename Allocator> | 843 template <typename T, size_t inlineCapacity, typename Allocator> |
| 896 template <typename U> | 844 template <typename U> |
| 897 bool Vector<T, inlineCapacity, Allocator>::contains(const U& value) const | 845 bool Vector<T, inlineCapacity, Allocator>::contains(const U& value) const { |
| 898 { | 846 return find(value) != kNotFound; |
| 899 return find(value) != kNotFound; | |
| 900 } | 847 } |
| 901 | 848 |
| 902 template <typename T, size_t inlineCapacity, typename Allocator> | 849 template <typename T, size_t inlineCapacity, typename Allocator> |
| 903 template <typename U> | 850 template <typename U> |
| 904 size_t Vector<T, inlineCapacity, Allocator>::find(const U& value) const | 851 size_t Vector<T, inlineCapacity, Allocator>::find(const U& value) const { |
| 905 { | 852 const T* b = begin(); |
| 906 const T* b = begin(); | 853 const T* e = end(); |
| 907 const T* e = end(); | 854 for (const T* iter = b; iter < e; ++iter) { |
| 908 for (const T* iter = b; iter < e; ++iter) { | 855 if (*iter == value) |
| 909 if (*iter == value) | 856 return iter - b; |
| 910 return iter - b; | 857 } |
| 911 } | 858 return kNotFound; |
| 912 return kNotFound; | |
| 913 } | 859 } |
| 914 | 860 |
| 915 template <typename T, size_t inlineCapacity, typename Allocator> | 861 template <typename T, size_t inlineCapacity, typename Allocator> |
| 916 template <typename U> | 862 template <typename U> |
| 917 size_t Vector<T, inlineCapacity, Allocator>::reverseFind(const U& value) const | 863 size_t Vector<T, inlineCapacity, Allocator>::reverseFind(const U& value) const { |
| 918 { | 864 const T* b = begin(); |
| 919 const T* b = begin(); | 865 const T* iter = end(); |
| 920 const T* iter = end(); | 866 while (iter > b) { |
| 921 while (iter > b) { | 867 --iter; |
| 922 --iter; | 868 if (*iter == value) |
| 923 if (*iter == value) | 869 return iter - b; |
| 924 return iter - b; | 870 } |
| 925 } | 871 return kNotFound; |
| 926 return kNotFound; | 872 } |
| 927 } | 873 |
| 928 | 874 template <typename T, size_t inlineCapacity, typename Allocator> |
| 929 template <typename T, size_t inlineCapacity, typename Allocator> | 875 void Vector<T, inlineCapacity, Allocator>::fill(const T& val, size_t newSize) { |
| 930 void Vector<T, inlineCapacity, Allocator>::fill(const T& val, size_t newSize) | 876 if (size() > newSize) { |
| 931 { | 877 shrink(newSize); |
| 932 if (size() > newSize) { | 878 } else if (newSize > capacity()) { |
| 933 shrink(newSize); | 879 clear(); |
| 934 } else if (newSize > capacity()) { | 880 reserveCapacity(newSize); |
| 935 clear(); | 881 ASSERT(begin()); |
| 936 reserveCapacity(newSize); | 882 } |
| 937 ASSERT(begin()); | 883 |
| 938 } | 884 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize); |
| 939 | 885 std::fill(begin(), end(), val); |
| 940 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize); | 886 TypeOperations::uninitializedFill(end(), begin() + newSize, val); |
| 941 std::fill(begin(), end(), val); | 887 m_size = newSize; |
| 942 TypeOperations::uninitializedFill(end(), begin() + newSize, val); | |
| 943 m_size = newSize; | |
| 944 } | 888 } |
| 945 | 889 |
| 946 template <typename T, size_t inlineCapacity, typename Allocator> | 890 template <typename T, size_t inlineCapacity, typename Allocator> |
| 947 template <typename Iterator> | 891 template <typename Iterator> |
| 948 void Vector<T, inlineCapacity, Allocator>::appendRange(Iterator start, Iterator
end) | 892 void Vector<T, inlineCapacity, Allocator>::appendRange(Iterator start, Iterator
end) { |
| 949 { | 893 for (Iterator it = start; it != end; ++it) |
| 950 for (Iterator it = start; it != end; ++it) | 894 append(*it); |
| 951 append(*it); | 895 } |
| 952 } | 896 |
| 953 | 897 template <typename T, size_t inlineCapacity, typename Allocator> |
| 954 template <typename T, size_t inlineCapacity, typename Allocator> | 898 void Vector<T, inlineCapacity, Allocator>::expandCapacity(size_t newMinCapacity)
{ |
| 955 void Vector<T, inlineCapacity, Allocator>::expandCapacity(size_t newMinCapacity) | 899 size_t oldCapacity = capacity(); |
| 956 { | 900 size_t expandedCapacity = oldCapacity; |
| 957 size_t oldCapacity = capacity(); | 901 // We use a more aggressive expansion strategy for Vectors with inline |
| 958 size_t expandedCapacity = oldCapacity; | 902 // storage. This is because they are more likely to be on the stack, so the |
| 959 // We use a more aggressive expansion strategy for Vectors with inline | 903 // risk of heap bloat is minimized. Furthermore, exceeding the inline |
| 960 // storage. This is because they are more likely to be on the stack, so the | 904 // capacity limit is not supposed to happen in the common case and may |
| 961 // risk of heap bloat is minimized. Furthermore, exceeding the inline | 905 // indicate a pathological condition or microbenchmark. |
| 962 // capacity limit is not supposed to happen in the common case and may | 906 if (INLINE_CAPACITY) { |
| 963 // indicate a pathological condition or microbenchmark. | 907 expandedCapacity *= 2; |
| 964 if (INLINE_CAPACITY) { | 908 // Check for integer overflow, which could happen in the 32-bit build. |
| 965 expandedCapacity *= 2; | 909 RELEASE_ASSERT(expandedCapacity > oldCapacity); |
| 966 // Check for integer overflow, which could happen in the 32-bit build. | 910 } else { |
| 967 RELEASE_ASSERT(expandedCapacity > oldCapacity); | 911 // This cannot integer overflow. |
| 968 } else { | 912 // On 64-bit, the "expanded" integer is 32-bit, and any encroachment |
| 969 // This cannot integer overflow. | 913 // above 2^32 will fail allocation in allocateBuffer(). On 32-bit, |
| 970 // On 64-bit, the "expanded" integer is 32-bit, and any encroachment | 914 // there's not enough address space to hold the old and new buffers. In |
| 971 // above 2^32 will fail allocation in allocateBuffer(). On 32-bit, | 915 // addition, our underlying allocator is supposed to always fail on > |
| 972 // there's not enough address space to hold the old and new buffers. In | 916 // (2^31 - 1) allocations. |
| 973 // addition, our underlying allocator is supposed to always fail on > | 917 expandedCapacity += (expandedCapacity / 4) + 1; |
| 974 // (2^31 - 1) allocations. | 918 } |
| 975 expandedCapacity += (expandedCapacity / 4) + 1; | 919 reserveCapacity(std::max(newMinCapacity, std::max(static_cast<size_t>(kInitial
VectorSize), expandedCapacity))); |
| 976 } | 920 } |
| 977 reserveCapacity(std::max(newMinCapacity, std::max(static_cast<size_t>(kIniti
alVectorSize), expandedCapacity))); | 921 |
| 978 } | 922 template <typename T, size_t inlineCapacity, typename Allocator> |
| 979 | 923 const T* Vector<T, inlineCapacity, Allocator>::expandCapacity(size_t newMinCapac
ity, const T* ptr) { |
| 980 template <typename T, size_t inlineCapacity, typename Allocator> | 924 if (ptr < begin() || ptr >= end()) { |
| 981 const T* Vector<T, inlineCapacity, Allocator>::expandCapacity(size_t newMinCapac
ity, const T* ptr) | |
| 982 { | |
| 983 if (ptr < begin() || ptr >= end()) { | |
| 984 expandCapacity(newMinCapacity); | |
| 985 return ptr; | |
| 986 } | |
| 987 size_t index = ptr - begin(); | |
| 988 expandCapacity(newMinCapacity); | |
| 989 return begin() + index; | |
| 990 } | |
| 991 | |
| 992 template <typename T, size_t inlineCapacity, typename Allocator> | |
| 993 template <typename U> | |
| 994 inline U* Vector<T, inlineCapacity, Allocator>::expandCapacity(size_t newMinCapa
city, U* ptr) | |
| 995 { | |
| 996 expandCapacity(newMinCapacity); | 925 expandCapacity(newMinCapacity); |
| 997 return ptr; | 926 return ptr; |
| 998 } | 927 } |
| 999 | 928 size_t index = ptr - begin(); |
| 1000 template <typename T, size_t inlineCapacity, typename Allocator> | 929 expandCapacity(newMinCapacity); |
| 1001 inline void Vector<T, inlineCapacity, Allocator>::resize(size_t size) | 930 return begin() + index; |
| 1002 { | 931 } |
| 1003 if (size <= m_size) { | 932 |
| 1004 TypeOperations::destruct(begin() + size, end()); | 933 template <typename T, size_t inlineCapacity, typename Allocator> |
| 1005 clearUnusedSlots(begin() + size, end()); | 934 template <typename U> |
| 1006 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size); | 935 inline U* Vector<T, inlineCapacity, Allocator>::expandCapacity(size_t newMinCapa
city, U* ptr) { |
| 1007 } else { | 936 expandCapacity(newMinCapacity); |
| 1008 if (size > capacity()) | 937 return ptr; |
| 1009 expandCapacity(size); | 938 } |
| 1010 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size); | 939 |
| 1011 TypeOperations::initialize(end(), begin() + size); | 940 template <typename T, size_t inlineCapacity, typename Allocator> |
| 1012 } | 941 inline void Vector<T, inlineCapacity, Allocator>::resize(size_t size) { |
| 1013 | 942 if (size <= m_size) { |
| 1014 m_size = size; | |
| 1015 } | |
| 1016 | |
| 1017 template <typename T, size_t inlineCapacity, typename Allocator> | |
| 1018 void Vector<T, inlineCapacity, Allocator>::shrink(size_t size) | |
| 1019 { | |
| 1020 ASSERT(size <= m_size); | |
| 1021 TypeOperations::destruct(begin() + size, end()); | 943 TypeOperations::destruct(begin() + size, end()); |
| 1022 clearUnusedSlots(begin() + size, end()); | 944 clearUnusedSlots(begin() + size, end()); |
| 1023 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size); | 945 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size); |
| 1024 m_size = size; | 946 } else { |
| 1025 } | |
| 1026 | |
| 1027 template <typename T, size_t inlineCapacity, typename Allocator> | |
| 1028 void Vector<T, inlineCapacity, Allocator>::grow(size_t size) | |
| 1029 { | |
| 1030 ASSERT(size >= m_size); | |
| 1031 if (size > capacity()) | 947 if (size > capacity()) |
| 1032 expandCapacity(size); | 948 expandCapacity(size); |
| 1033 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size); | 949 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size); |
| 1034 TypeOperations::initialize(end(), begin() + size); | 950 TypeOperations::initialize(end(), begin() + size); |
| 1035 m_size = size; | 951 } |
| 1036 } | 952 |
| 1037 | 953 m_size = size; |
| 1038 template <typename T, size_t inlineCapacity, typename Allocator> | 954 } |
| 1039 void Vector<T, inlineCapacity, Allocator>::reserveCapacity(size_t newCapacity) | 955 |
| 1040 { | 956 template <typename T, size_t inlineCapacity, typename Allocator> |
| 1041 if (UNLIKELY(newCapacity <= capacity())) | 957 void Vector<T, inlineCapacity, Allocator>::shrink(size_t size) { |
| 1042 return; | 958 ASSERT(size <= m_size); |
| 1043 T* oldBuffer = begin(); | 959 TypeOperations::destruct(begin() + size, end()); |
| 1044 if (!oldBuffer) { | 960 clearUnusedSlots(begin() + size, end()); |
| 1045 Base::allocateBuffer(newCapacity); | 961 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size); |
| 1046 return; | 962 m_size = size; |
| 1047 } | 963 } |
| 964 |
| 965 template <typename T, size_t inlineCapacity, typename Allocator> |
| 966 void Vector<T, inlineCapacity, Allocator>::grow(size_t size) { |
| 967 ASSERT(size >= m_size); |
| 968 if (size > capacity()) |
| 969 expandCapacity(size); |
| 970 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size); |
| 971 TypeOperations::initialize(end(), begin() + size); |
| 972 m_size = size; |
| 973 } |
| 974 |
| 975 template <typename T, size_t inlineCapacity, typename Allocator> |
| 976 void Vector<T, inlineCapacity, Allocator>::reserveCapacity(size_t newCapacity) { |
| 977 if (UNLIKELY(newCapacity <= capacity())) |
| 978 return; |
| 979 T* oldBuffer = begin(); |
| 980 if (!oldBuffer) { |
| 981 Base::allocateBuffer(newCapacity); |
| 982 return; |
| 983 } |
| 1048 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER | 984 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER |
| 1049 size_t oldCapacity = capacity(); | 985 size_t oldCapacity = capacity(); |
| 1050 #endif | 986 #endif |
| 1051 // The Allocator::isGarbageCollected check is not needed. The check is just | 987 // The Allocator::isGarbageCollected check is not needed. The check is just |
| 1052 // a static hint for a compiler to indicate that Base::expandBuffer returns | 988 // a static hint for a compiler to indicate that Base::expandBuffer returns |
| 1053 // false if Allocator is a PartitionAllocator. | 989 // false if Allocator is a PartitionAllocator. |
| 1054 if (Allocator::isGarbageCollected && Base::expandBuffer(newCapacity)) { | 990 if (Allocator::isGarbageCollected && Base::expandBuffer(newCapacity)) { |
| 1055 ANNOTATE_CHANGE_CAPACITY(begin(), oldCapacity, m_size, capacity()); | 991 ANNOTATE_CHANGE_CAPACITY(begin(), oldCapacity, m_size, capacity()); |
| 1056 return; | 992 return; |
| 1057 } | 993 } |
| 994 T* oldEnd = end(); |
| 995 Base::allocateExpandedBuffer(newCapacity); |
| 996 ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size); |
| 997 TypeOperations::move(oldBuffer, oldEnd, begin()); |
| 998 clearUnusedSlots(oldBuffer, oldEnd); |
| 999 ANNOTATE_DELETE_BUFFER(oldBuffer, oldCapacity, m_size); |
| 1000 Base::deallocateBuffer(oldBuffer); |
| 1001 } |
| 1002 |
| 1003 template <typename T, size_t inlineCapacity, typename Allocator> |
| 1004 inline void Vector<T, inlineCapacity, Allocator>::reserveInitialCapacity(size_t
initialCapacity) { |
| 1005 ASSERT(!m_size); |
| 1006 ASSERT(capacity() == INLINE_CAPACITY); |
| 1007 if (initialCapacity > INLINE_CAPACITY) { |
| 1008 ANNOTATE_DELETE_BUFFER(begin(), capacity(), m_size); |
| 1009 Base::allocateBuffer(initialCapacity); |
| 1010 ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size); |
| 1011 } |
| 1012 } |
| 1013 |
| 1014 template <typename T, size_t inlineCapacity, typename Allocator> |
| 1015 void Vector<T, inlineCapacity, Allocator>::shrinkCapacity(size_t newCapacity) { |
| 1016 if (newCapacity >= capacity()) |
| 1017 return; |
| 1018 |
| 1019 if (newCapacity < size()) |
| 1020 shrink(newCapacity); |
| 1021 |
| 1022 T* oldBuffer = begin(); |
| 1023 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER |
| 1024 size_t oldCapacity = capacity(); |
| 1025 #endif |
| 1026 if (newCapacity > 0) { |
| 1027 if (Base::shrinkBuffer(newCapacity)) { |
| 1028 ANNOTATE_CHANGE_CAPACITY(begin(), oldCapacity, m_size, capacity()); |
| 1029 return; |
| 1030 } |
| 1031 |
| 1058 T* oldEnd = end(); | 1032 T* oldEnd = end(); |
| 1059 Base::allocateExpandedBuffer(newCapacity); | 1033 Base::allocateBuffer(newCapacity); |
| 1060 ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size); | 1034 if (begin() != oldBuffer) { |
| 1061 TypeOperations::move(oldBuffer, oldEnd, begin()); | 1035 ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size); |
| 1062 clearUnusedSlots(oldBuffer, oldEnd); | 1036 TypeOperations::move(oldBuffer, oldEnd, begin()); |
| 1063 ANNOTATE_DELETE_BUFFER(oldBuffer, oldCapacity, m_size); | 1037 clearUnusedSlots(oldBuffer, oldEnd); |
| 1064 Base::deallocateBuffer(oldBuffer); | 1038 ANNOTATE_DELETE_BUFFER(oldBuffer, oldCapacity, m_size); |
| 1065 } | 1039 } |
| 1066 | 1040 } else { |
| 1067 template <typename T, size_t inlineCapacity, typename Allocator> | 1041 Base::resetBufferPointer(); |
| 1068 inline void Vector<T, inlineCapacity, Allocator>::reserveInitialCapacity(size_t
initialCapacity) | |
| 1069 { | |
| 1070 ASSERT(!m_size); | |
| 1071 ASSERT(capacity() == INLINE_CAPACITY); | |
| 1072 if (initialCapacity > INLINE_CAPACITY) { | |
| 1073 ANNOTATE_DELETE_BUFFER(begin(), capacity(), m_size); | |
| 1074 Base::allocateBuffer(initialCapacity); | |
| 1075 ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size); | |
| 1076 } | |
| 1077 } | |
| 1078 | |
| 1079 template <typename T, size_t inlineCapacity, typename Allocator> | |
| 1080 void Vector<T, inlineCapacity, Allocator>::shrinkCapacity(size_t newCapacity) | |
| 1081 { | |
| 1082 if (newCapacity >= capacity()) | |
| 1083 return; | |
| 1084 | |
| 1085 if (newCapacity < size()) | |
| 1086 shrink(newCapacity); | |
| 1087 | |
| 1088 T* oldBuffer = begin(); | |
| 1089 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER | 1042 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER |
| 1090 size_t oldCapacity = capacity(); | 1043 if (oldBuffer != begin()) { |
| 1044 ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size); |
| 1045 ANNOTATE_DELETE_BUFFER(oldBuffer, oldCapacity, m_size); |
| 1046 } |
| 1091 #endif | 1047 #endif |
| 1092 if (newCapacity > 0) { | 1048 } |
| 1093 if (Base::shrinkBuffer(newCapacity)) { | 1049 |
| 1094 ANNOTATE_CHANGE_CAPACITY(begin(), oldCapacity, m_size, capacity()); | 1050 Base::deallocateBuffer(oldBuffer); |
| 1095 return; | |
| 1096 } | |
| 1097 | |
| 1098 T* oldEnd = end(); | |
| 1099 Base::allocateBuffer(newCapacity); | |
| 1100 if (begin() != oldBuffer) { | |
| 1101 ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size); | |
| 1102 TypeOperations::move(oldBuffer, oldEnd, begin()); | |
| 1103 clearUnusedSlots(oldBuffer, oldEnd); | |
| 1104 ANNOTATE_DELETE_BUFFER(oldBuffer, oldCapacity, m_size); | |
| 1105 } | |
| 1106 } else { | |
| 1107 Base::resetBufferPointer(); | |
| 1108 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER | |
| 1109 if (oldBuffer != begin()) { | |
| 1110 ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size); | |
| 1111 ANNOTATE_DELETE_BUFFER(oldBuffer, oldCapacity, m_size); | |
| 1112 } | |
| 1113 #endif | |
| 1114 } | |
| 1115 | |
| 1116 Base::deallocateBuffer(oldBuffer); | |
| 1117 } | 1051 } |
| 1118 | 1052 |
| 1119 // Templatizing these is better than just letting the conversion happen | 1053 // Templatizing these is better than just letting the conversion happen |
| 1120 // implicitly, because for instance it allows a PassRefPtr to be appended to a | 1054 // implicitly, because for instance it allows a PassRefPtr to be appended to a |
| 1121 // RefPtr vector without refcount thrash. | 1055 // RefPtr vector without refcount thrash. |
| 1122 | 1056 |
| 1123 template <typename T, size_t inlineCapacity, typename Allocator> | 1057 template <typename T, size_t inlineCapacity, typename Allocator> |
| 1124 template <typename U> | 1058 template <typename U> |
| 1125 void Vector<T, inlineCapacity, Allocator>::append(const U* data, size_t dataSize
) | 1059 void Vector<T, inlineCapacity, Allocator>::append(const U* data, size_t dataSize
) { |
| 1126 { | 1060 ASSERT(Allocator::isAllocationAllowed()); |
| 1127 ASSERT(Allocator::isAllocationAllowed()); | 1061 size_t newSize = m_size + dataSize; |
| 1128 size_t newSize = m_size + dataSize; | 1062 if (newSize > capacity()) { |
| 1129 if (newSize > capacity()) { | 1063 data = expandCapacity(newSize, data); |
| 1130 data = expandCapacity(newSize, data); | 1064 ASSERT(begin()); |
| 1131 ASSERT(begin()); | 1065 } |
| 1132 } | 1066 RELEASE_ASSERT(newSize >= m_size); |
| 1133 RELEASE_ASSERT(newSize >= m_size); | 1067 T* dest = end(); |
| 1134 T* dest = end(); | 1068 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize); |
| 1135 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize); | 1069 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(data, &
data[dataSize], dest); |
| 1136 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(data,
&data[dataSize], dest); | 1070 m_size = newSize; |
| 1137 m_size = newSize; | |
| 1138 } | 1071 } |
| 1139 | 1072 |
| 1140 template <typename T, size_t inlineCapacity, typename Allocator> | 1073 template <typename T, size_t inlineCapacity, typename Allocator> |
| 1141 template <typename U> | 1074 template <typename U> |
| 1142 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::append(const U& val) | 1075 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::append(const U& val) { |
| 1143 { | 1076 ASSERT(Allocator::isAllocationAllowed()); |
| 1144 ASSERT(Allocator::isAllocationAllowed()); | 1077 if (LIKELY(size() != capacity())) { |
| 1145 if (LIKELY(size() != capacity())) { | 1078 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); |
| 1146 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); | 1079 new (NotNull, end()) T(val); |
| 1147 new (NotNull, end()) T(val); | 1080 ++m_size; |
| 1148 ++m_size; | 1081 return; |
| 1149 return; | 1082 } |
| 1150 } | |
| 1151 | 1083 |
| 1152 appendSlowCase(val); | 1084 appendSlowCase(val); |
| 1153 } | 1085 } |
| 1154 | 1086 |
| 1155 template <typename T, size_t inlineCapacity, typename Allocator> | 1087 template <typename T, size_t inlineCapacity, typename Allocator> |
| 1156 template <typename U> | 1088 template <typename U> |
| 1157 NEVER_INLINE void Vector<T, inlineCapacity, Allocator>::appendSlowCase(const U&
val) | 1089 NEVER_INLINE void Vector<T, inlineCapacity, Allocator>::appendSlowCase(const U&
val) { |
| 1158 { | 1090 ASSERT(size() == capacity()); |
| 1159 ASSERT(size() == capacity()); | |
| 1160 | 1091 |
| 1161 const U* ptr = &val; | 1092 const U* ptr = &val; |
| 1162 ptr = expandCapacity(size() + 1, ptr); | 1093 ptr = expandCapacity(size() + 1, ptr); |
| 1163 ASSERT(begin()); | 1094 ASSERT(begin()); |
| 1164 | 1095 |
| 1165 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); | 1096 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); |
| 1166 new (NotNull, end()) T(*ptr); | 1097 new (NotNull, end()) T(*ptr); |
| 1167 ++m_size; | 1098 ++m_size; |
| 1168 } | 1099 } |
| 1169 | 1100 |
| 1170 // This version of append saves a branch in the case where you know that the | 1101 // This version of append saves a branch in the case where you know that the |
| 1171 // vector's capacity is large enough for the append to succeed. | 1102 // vector's capacity is large enough for the append to succeed. |
| 1172 | 1103 |
| 1173 template <typename T, size_t inlineCapacity, typename Allocator> | 1104 template <typename T, size_t inlineCapacity, typename Allocator> |
| 1174 template <typename U> | 1105 template <typename U> |
| 1175 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::uncheckedAppend(const U
& val) | 1106 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::uncheckedAppend(const U
& val) { |
| 1176 { | |
| 1177 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER | 1107 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER |
| 1178 // Vectors in ASAN builds don't have inlineCapacity. | 1108 // Vectors in ASAN builds don't have inlineCapacity. |
| 1179 append(val); | 1109 append(val); |
| 1180 #else | 1110 #else |
| 1181 ASSERT(size() < capacity()); | 1111 ASSERT(size() < capacity()); |
| 1182 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); | 1112 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); |
| 1183 const U* ptr = &val; | 1113 const U* ptr = &val; |
| 1184 new (NotNull, end()) T(*ptr); | 1114 new (NotNull, end()) T(*ptr); |
| 1185 ++m_size; | 1115 ++m_size; |
| 1186 #endif | 1116 #endif |
| 1187 } | 1117 } |
| 1188 | 1118 |
| 1189 template <typename T, size_t inlineCapacity, typename Allocator> | 1119 template <typename T, size_t inlineCapacity, typename Allocator> |
| 1190 template <typename U, size_t otherCapacity, typename OtherAllocator> | 1120 template <typename U, size_t otherCapacity, typename OtherAllocator> |
| 1191 inline void Vector<T, inlineCapacity, Allocator>::appendVector(const Vector<U, o
therCapacity, OtherAllocator>& val) | 1121 inline void Vector<T, inlineCapacity, Allocator>::appendVector(const Vector<U, o
therCapacity, OtherAllocator>& val) { |
| 1192 { | 1122 append(val.begin(), val.size()); |
| 1193 append(val.begin(), val.size()); | |
| 1194 } | 1123 } |
| 1195 | 1124 |
| 1196 template <typename T, size_t inlineCapacity, typename Allocator> | 1125 template <typename T, size_t inlineCapacity, typename Allocator> |
| 1197 template <typename U> | 1126 template <typename U> |
| 1198 void Vector<T, inlineCapacity, Allocator>::insert(size_t position, const U* data
, size_t dataSize) | 1127 void Vector<T, inlineCapacity, Allocator>::insert(size_t position, const U* data
, size_t dataSize) { |
| 1199 { | 1128 ASSERT(Allocator::isAllocationAllowed()); |
| 1200 ASSERT(Allocator::isAllocationAllowed()); | 1129 RELEASE_ASSERT(position <= size()); |
| 1201 RELEASE_ASSERT(position <= size()); | 1130 size_t newSize = m_size + dataSize; |
| 1202 size_t newSize = m_size + dataSize; | 1131 if (newSize > capacity()) { |
| 1203 if (newSize > capacity()) { | 1132 data = expandCapacity(newSize, data); |
| 1204 data = expandCapacity(newSize, data); | 1133 ASSERT(begin()); |
| 1205 ASSERT(begin()); | 1134 } |
| 1206 } | 1135 RELEASE_ASSERT(newSize >= m_size); |
| 1207 RELEASE_ASSERT(newSize >= m_size); | 1136 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize); |
| 1208 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize); | 1137 T* spot = begin() + position; |
| 1209 T* spot = begin() + position; | 1138 TypeOperations::moveOverlapping(spot, end(), spot + dataSize); |
| 1210 TypeOperations::moveOverlapping(spot, end(), spot + dataSize); | 1139 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(data, &
data[dataSize], spot); |
| 1211 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(data,
&data[dataSize], spot); | 1140 m_size = newSize; |
| 1212 m_size = newSize; | |
| 1213 } | 1141 } |
| 1214 | 1142 |
| 1215 template <typename T, size_t inlineCapacity, typename Allocator> | 1143 template <typename T, size_t inlineCapacity, typename Allocator> |
| 1216 template <typename U> | 1144 template <typename U> |
| 1217 inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, const
U& val) | 1145 inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, const
U& val) { |
| 1218 { | 1146 ASSERT(Allocator::isAllocationAllowed()); |
| 1219 ASSERT(Allocator::isAllocationAllowed()); | 1147 RELEASE_ASSERT(position <= size()); |
| 1220 RELEASE_ASSERT(position <= size()); | 1148 const U* data = &val; |
| 1221 const U* data = &val; | 1149 if (size() == capacity()) { |
| 1222 if (size() == capacity()) { | 1150 data = expandCapacity(size() + 1, data); |
| 1223 data = expandCapacity(size() + 1, data); | 1151 ASSERT(begin()); |
| 1224 ASSERT(begin()); | 1152 } |
| 1225 } | 1153 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); |
| 1226 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); | 1154 T* spot = begin() + position; |
| 1227 T* spot = begin() + position; | 1155 TypeOperations::moveOverlapping(spot, end(), spot + 1); |
| 1228 TypeOperations::moveOverlapping(spot, end(), spot + 1); | 1156 new (NotNull, spot) T(*data); |
| 1229 new (NotNull, spot) T(*data); | 1157 ++m_size; |
| 1230 ++m_size; | |
| 1231 } | 1158 } |
| 1232 | 1159 |
| 1233 template <typename T, size_t inlineCapacity, typename Allocator> | 1160 template <typename T, size_t inlineCapacity, typename Allocator> |
| 1234 template <typename U, size_t c, typename OtherAllocator> | 1161 template <typename U, size_t c, typename OtherAllocator> |
| 1235 inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, const
Vector<U, c, OtherAllocator>& val) | 1162 inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, const
Vector<U, c, OtherAllocator>& val) { |
| 1236 { | 1163 insert(position, val.begin(), val.size()); |
| 1237 insert(position, val.begin(), val.size()); | |
| 1238 } | 1164 } |
| 1239 | 1165 |
| 1240 template <typename T, size_t inlineCapacity, typename Allocator> | 1166 template <typename T, size_t inlineCapacity, typename Allocator> |
| 1241 template <typename U> | 1167 template <typename U> |
| 1242 void Vector<T, inlineCapacity, Allocator>::prepend(const U* data, size_t dataSiz
e) | 1168 void Vector<T, inlineCapacity, Allocator>::prepend(const U* data, size_t dataSiz
e) { |
| 1243 { | 1169 insert(0, data, dataSize); |
| 1244 insert(0, data, dataSize); | |
| 1245 } | 1170 } |
| 1246 | 1171 |
| 1247 template <typename T, size_t inlineCapacity, typename Allocator> | 1172 template <typename T, size_t inlineCapacity, typename Allocator> |
| 1248 template <typename U> | 1173 template <typename U> |
| 1249 inline void Vector<T, inlineCapacity, Allocator>::prepend(const U& val) | 1174 inline void Vector<T, inlineCapacity, Allocator>::prepend(const U& val) { |
| 1250 { | 1175 insert(0, val); |
| 1251 insert(0, val); | |
| 1252 } | 1176 } |
| 1253 | 1177 |
| 1254 template <typename T, size_t inlineCapacity, typename Allocator> | 1178 template <typename T, size_t inlineCapacity, typename Allocator> |
| 1255 template <typename U, size_t c, typename V> | 1179 template <typename U, size_t c, typename V> |
| 1256 inline void Vector<T, inlineCapacity, Allocator>::prepend(const Vector<U, c, V>&
val) | 1180 inline void Vector<T, inlineCapacity, Allocator>::prepend(const Vector<U, c, V>&
val) { |
| 1257 { | 1181 insert(0, val.begin(), val.size()); |
| 1258 insert(0, val.begin(), val.size()); | |
| 1259 } | 1182 } |
| 1260 | 1183 |
| 1261 template <typename T, size_t inlineCapacity, typename Allocator> | 1184 template <typename T, size_t inlineCapacity, typename Allocator> |
| 1262 inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position) | 1185 inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position) { |
| 1263 { | 1186 RELEASE_ASSERT(position < size()); |
| 1264 RELEASE_ASSERT(position < size()); | 1187 T* spot = begin() + position; |
| 1265 T* spot = begin() + position; | 1188 spot->~T(); |
| 1266 spot->~T(); | 1189 TypeOperations::moveOverlapping(spot + 1, end(), spot); |
| 1267 TypeOperations::moveOverlapping(spot + 1, end(), spot); | 1190 clearUnusedSlots(end() - 1, end()); |
| 1268 clearUnusedSlots(end() - 1, end()); | 1191 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size - 1); |
| 1269 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size - 1); | 1192 --m_size; |
| 1270 --m_size; | |
| 1271 } | 1193 } |
| 1272 | 1194 |
| 1273 template <typename T, size_t inlineCapacity, typename Allocator> | 1195 template <typename T, size_t inlineCapacity, typename Allocator> |
| 1274 inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position, size_t
length) | 1196 inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position, size_t
length) { |
| 1275 { | 1197 ASSERT_WITH_SECURITY_IMPLICATION(position <= size()); |
| 1276 ASSERT_WITH_SECURITY_IMPLICATION(position <= size()); | 1198 if (!length) |
| 1277 if (!length) | 1199 return; |
| 1278 return; | 1200 RELEASE_ASSERT(position + length <= size()); |
| 1279 RELEASE_ASSERT(position + length <= size()); | 1201 T* beginSpot = begin() + position; |
| 1280 T* beginSpot = begin() + position; | 1202 T* endSpot = beginSpot + length; |
| 1281 T* endSpot = beginSpot + length; | 1203 TypeOperations::destruct(beginSpot, endSpot); |
| 1282 TypeOperations::destruct(beginSpot, endSpot); | 1204 TypeOperations::moveOverlapping(endSpot, end(), beginSpot); |
| 1283 TypeOperations::moveOverlapping(endSpot, end(), beginSpot); | 1205 clearUnusedSlots(end() - length, end()); |
| 1284 clearUnusedSlots(end() - length, end()); | 1206 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size - length); |
| 1285 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size - length); | 1207 m_size -= length; |
| 1286 m_size -= length; | |
| 1287 } | 1208 } |
| 1288 | 1209 |
| 1289 template <typename T, size_t inlineCapacity, typename Allocator> | 1210 template <typename T, size_t inlineCapacity, typename Allocator> |
| 1290 inline void Vector<T, inlineCapacity, Allocator>::reverse() | 1211 inline void Vector<T, inlineCapacity, Allocator>::reverse() { |
| 1291 { | 1212 for (size_t i = 0; i < m_size / 2; ++i) |
| 1292 for (size_t i = 0; i < m_size / 2; ++i) | 1213 std::swap(at(i), at(m_size - 1 - i)); |
| 1293 std::swap(at(i), at(m_size - 1 - i)); | |
| 1294 } | 1214 } |
| 1295 | 1215 |
| 1296 template <typename T, size_t inlineCapacity, typename Allocator> | 1216 template <typename T, size_t inlineCapacity, typename Allocator> |
| 1297 inline void swap(Vector<T, inlineCapacity, Allocator>& a, Vector<T, inlineCapaci
ty, Allocator>& b) | 1217 inline void swap(Vector<T, inlineCapacity, Allocator>& a, Vector<T, inlineCapaci
ty, Allocator>& b) { |
| 1298 { | 1218 a.swap(b); |
| 1299 a.swap(b); | |
| 1300 } | 1219 } |
| 1301 | 1220 |
| 1302 template <typename T, size_t inlineCapacityA, size_t inlineCapacityB, typename A
llocator> | 1221 template <typename T, size_t inlineCapacityA, size_t inlineCapacityB, typename A
llocator> |
| 1303 bool operator==(const Vector<T, inlineCapacityA, Allocator>& a, const Vector<T,
inlineCapacityB, Allocator>& b) | 1222 bool operator==(const Vector<T, inlineCapacityA, Allocator>& a, const Vector<T,
inlineCapacityB, Allocator>& b) { |
| 1304 { | 1223 if (a.size() != b.size()) |
| 1305 if (a.size() != b.size()) | 1224 return false; |
| 1306 return false; | 1225 if (a.isEmpty()) |
| 1307 if (a.isEmpty()) | 1226 return true; |
| 1308 return true; | 1227 return VectorTypeOperations<T>::compare(a.data(), b.data(), a.size()); |
| 1309 return VectorTypeOperations<T>::compare(a.data(), b.data(), a.size()); | |
| 1310 } | 1228 } |
| 1311 | 1229 |
| 1312 template <typename T, size_t inlineCapacityA, size_t inlineCapacityB, typename A
llocator> | 1230 template <typename T, size_t inlineCapacityA, size_t inlineCapacityB, typename A
llocator> |
| 1313 inline bool operator!=(const Vector<T, inlineCapacityA, Allocator>& a, const Vec
tor<T, inlineCapacityB, Allocator>& b) | 1231 inline bool operator!=(const Vector<T, inlineCapacityA, Allocator>& a, const Vec
tor<T, inlineCapacityB, Allocator>& b) { |
| 1314 { | 1232 return !(a == b); |
| 1315 return !(a == b); | |
| 1316 } | 1233 } |
| 1317 | 1234 |
| 1318 // This is only called if the allocator is a HeapAllocator. It is used when | 1235 // This is only called if the allocator is a HeapAllocator. It is used when |
| 1319 // visiting during a tracing GC. | 1236 // visiting during a tracing GC. |
| 1320 template <typename T, size_t inlineCapacity, typename Allocator> | 1237 template <typename T, size_t inlineCapacity, typename Allocator> |
| 1321 template <typename VisitorDispatcher> | 1238 template <typename VisitorDispatcher> |
| 1322 void Vector<T, inlineCapacity, Allocator>::trace(VisitorDispatcher visitor) | 1239 void Vector<T, inlineCapacity, Allocator>::trace(VisitorDispatcher visitor) { |
| 1323 { | 1240 ASSERT(Allocator::isGarbageCollected); // Garbage collector must be enabled. |
| 1324 ASSERT(Allocator::isGarbageCollected); // Garbage collector must be enabled. | 1241 if (!buffer()) |
| 1325 if (!buffer()) | 1242 return; |
| 1326 return; | 1243 if (this->hasOutOfLineBuffer()) { |
| 1327 if (this->hasOutOfLineBuffer()) { | 1244 // This is a performance optimization for a case where the buffer has |
| 1328 // This is a performance optimization for a case where the buffer has | 1245 // been already traced by somewhere. This can happen if the conservative |
| 1329 // been already traced by somewhere. This can happen if the conservative | 1246 // scanning traced an on-stack (false-positive or real) pointer to the |
| 1330 // scanning traced an on-stack (false-positive or real) pointer to the | 1247 // HeapVector, and then visitor->trace() traces the HeapVector. |
| 1331 // HeapVector, and then visitor->trace() traces the HeapVector. | 1248 if (Allocator::isHeapObjectAlive(buffer())) |
| 1332 if (Allocator::isHeapObjectAlive(buffer())) | 1249 return; |
| 1333 return; | 1250 Allocator::markNoTracing(visitor, buffer()); |
| 1334 Allocator::markNoTracing(visitor, buffer()); | 1251 } |
| 1335 } | 1252 const T* bufferBegin = buffer(); |
| 1336 const T* bufferBegin = buffer(); | 1253 const T* bufferEnd = buffer() + size(); |
| 1337 const T* bufferEnd = buffer() + size(); | 1254 if (NeedsTracingTrait<VectorTraits<T>>::value) { |
| 1338 if (NeedsTracingTrait<VectorTraits<T>>::value) { | 1255 for (const T* bufferEntry = bufferBegin; bufferEntry != bufferEnd; bufferEnt
ry++) |
| 1339 for (const T* bufferEntry = bufferBegin; bufferEntry != bufferEnd; buffe
rEntry++) | 1256 Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>(visitor,
*const_cast<T*>(bufferEntry)); |
| 1340 Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>(vis
itor, *const_cast<T*>(bufferEntry)); | 1257 checkUnusedSlots(buffer() + size(), buffer() + capacity()); |
| 1341 checkUnusedSlots(buffer() + size(), buffer() + capacity()); | 1258 } |
| 1342 } | |
| 1343 } | 1259 } |
| 1344 | 1260 |
| 1345 #if !ENABLE(OILPAN) | 1261 #if !ENABLE(OILPAN) |
| 1346 template <typename T, size_t N> | 1262 template <typename T, size_t N> |
| 1347 struct NeedsTracing<Vector<T, N>> { | 1263 struct NeedsTracing<Vector<T, N>> { |
| 1348 static const bool value = false; | 1264 static const bool value = false; |
| 1349 }; | 1265 }; |
| 1350 #endif | 1266 #endif |
| 1351 | 1267 |
| 1352 } // namespace WTF | 1268 } // namespace WTF |
| 1353 | 1269 |
| 1354 using WTF::Vector; | 1270 using WTF::Vector; |
| 1355 | 1271 |
| 1356 #endif // WTF_Vector_h | 1272 #endif // WTF_Vector_h |
| OLD | NEW |