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

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

Issue 1436153002: Apply clang-format with Chromium-style without column limit. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/wtf/Utility.h ('k') | third_party/WebKit/Source/wtf/VectorTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. 2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
3 * 3 *
4 * This library is free software; you can redistribute it and/or 4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public 5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either 6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version. 7 * version 2 of the License, or (at your option) any later version.
8 * 8 *
9 * This library is distributed in the hope that it will be useful, 9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/wtf/Utility.h ('k') | third_party/WebKit/Source/wtf/VectorTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698