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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 } | 75 } |
76 }; | 76 }; |
77 | 77 |
78 template <bool unusedSlotsMustBeZeroed, typename T> | 78 template <bool unusedSlotsMustBeZeroed, typename T> |
79 struct VectorUnusedSlotClearer; | 79 struct VectorUnusedSlotClearer; |
80 | 80 |
81 template <typename T> | 81 template <typename T> |
82 struct VectorUnusedSlotClearer<false, T> { | 82 struct VectorUnusedSlotClearer<false, T> { |
83 STATIC_ONLY(VectorUnusedSlotClearer); | 83 STATIC_ONLY(VectorUnusedSlotClearer); |
84 static void clear(T*, T*) {} | 84 static void clear(T*, T*) {} |
85 #if ENABLE(ASSERT) | 85 #if DCHECK_IS_ON() |
86 static void checkCleared(const T*, const T*) {} | 86 static void checkCleared(const T*, const T*) {} |
87 #endif | 87 #endif |
88 }; | 88 }; |
89 | 89 |
90 template <typename T> | 90 template <typename T> |
91 struct VectorUnusedSlotClearer<true, T> { | 91 struct VectorUnusedSlotClearer<true, T> { |
92 STATIC_ONLY(VectorUnusedSlotClearer); | 92 STATIC_ONLY(VectorUnusedSlotClearer); |
93 static void clear(T* begin, T* end) { | 93 static void clear(T* begin, T* end) { |
94 memset(reinterpret_cast<void*>(begin), 0, sizeof(T) * (end - begin)); | 94 memset(reinterpret_cast<void*>(begin), 0, sizeof(T) * (end - begin)); |
95 } | 95 } |
96 | 96 |
97 #if ENABLE(ASSERT) | 97 #if DCHECK_IS_ON() |
98 static void checkCleared(const T* begin, const T* end) { | 98 static void checkCleared(const T* begin, const T* end) { |
99 const unsigned char* unusedArea = | 99 const unsigned char* unusedArea = |
100 reinterpret_cast<const unsigned char*>(begin); | 100 reinterpret_cast<const unsigned char*>(begin); |
101 const unsigned char* endAddress = | 101 const unsigned char* endAddress = |
102 reinterpret_cast<const unsigned char*>(end); | 102 reinterpret_cast<const unsigned char*>(end); |
103 ASSERT(endAddress >= unusedArea); | 103 DCHECK_GE(endAddress, unusedArea); |
104 for (int i = 0; i < endAddress - unusedArea; ++i) | 104 for (int i = 0; i < endAddress - unusedArea; ++i) |
105 ASSERT(!unusedArea[i]); | 105 DCHECK(!unusedArea[i]); |
106 } | 106 } |
107 #endif | 107 #endif |
108 }; | 108 }; |
109 | 109 |
110 template <bool canInitializeWithMemset, typename T> | 110 template <bool canInitializeWithMemset, typename T> |
111 struct VectorInitializer; | 111 struct VectorInitializer; |
112 | 112 |
113 template <typename T> | 113 template <typename T> |
114 struct VectorInitializer<false, T> { | 114 struct VectorInitializer<false, T> { |
115 STATIC_ONLY(VectorInitializer); | 115 STATIC_ONLY(VectorInitializer); |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 } | 238 } |
239 }; | 239 }; |
240 | 240 |
241 template <bool canCompareWithMemcmp, typename T> | 241 template <bool canCompareWithMemcmp, typename T> |
242 struct VectorComparer; | 242 struct VectorComparer; |
243 | 243 |
244 template <typename T> | 244 template <typename T> |
245 struct VectorComparer<false, T> { | 245 struct VectorComparer<false, T> { |
246 STATIC_ONLY(VectorComparer); | 246 STATIC_ONLY(VectorComparer); |
247 static bool compare(const T* a, const T* b, size_t size) { | 247 static bool compare(const T* a, const T* b, size_t size) { |
248 ASSERT(a); | 248 DCHECK(a); |
249 ASSERT(b); | 249 DCHECK(b); |
250 return std::equal(a, a + size, b); | 250 return std::equal(a, a + size, b); |
251 } | 251 } |
252 }; | 252 }; |
253 | 253 |
254 template <typename T> | 254 template <typename T> |
255 struct VectorComparer<true, T> { | 255 struct VectorComparer<true, T> { |
256 STATIC_ONLY(VectorComparer); | 256 STATIC_ONLY(VectorComparer); |
257 static bool compare(const T* a, const T* b, size_t size) { | 257 static bool compare(const T* a, const T* b, size_t size) { |
258 ASSERT(a); | 258 DCHECK(a); |
259 ASSERT(b); | 259 DCHECK(b); |
260 return memcmp(a, b, sizeof(T) * size) == 0; | 260 return memcmp(a, b, sizeof(T) * size) == 0; |
261 } | 261 } |
262 }; | 262 }; |
263 | 263 |
264 template <typename T> | 264 template <typename T> |
265 struct VectorElementComparer { | 265 struct VectorElementComparer { |
266 STATIC_ONLY(VectorElementComparer); | 266 STATIC_ONLY(VectorElementComparer); |
267 template <typename U> | 267 template <typename U> |
268 static bool compareElement(const T& left, const U& right) { | 268 static bool compareElement(const T& left, const U& right) { |
269 return left == right; | 269 return left == right; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 } | 327 } |
328 }; | 328 }; |
329 | 329 |
330 template <typename T, bool hasInlineCapacity, typename Allocator> | 330 template <typename T, bool hasInlineCapacity, typename Allocator> |
331 class VectorBufferBase { | 331 class VectorBufferBase { |
332 WTF_MAKE_NONCOPYABLE(VectorBufferBase); | 332 WTF_MAKE_NONCOPYABLE(VectorBufferBase); |
333 DISALLOW_NEW(); | 333 DISALLOW_NEW(); |
334 | 334 |
335 public: | 335 public: |
336 void allocateBuffer(size_t newCapacity) { | 336 void allocateBuffer(size_t newCapacity) { |
337 ASSERT(newCapacity); | 337 DCHECK(newCapacity); |
338 size_t sizeToAllocate = allocationSize(newCapacity); | 338 size_t sizeToAllocate = allocationSize(newCapacity); |
339 if (hasInlineCapacity) | 339 if (hasInlineCapacity) |
340 m_buffer = | 340 m_buffer = |
341 Allocator::template allocateInlineVectorBacking<T>(sizeToAllocate); | 341 Allocator::template allocateInlineVectorBacking<T>(sizeToAllocate); |
342 else | 342 else |
343 m_buffer = Allocator::template allocateVectorBacking<T>(sizeToAllocate); | 343 m_buffer = Allocator::template allocateVectorBacking<T>(sizeToAllocate); |
344 m_capacity = sizeToAllocate / sizeof(T); | 344 m_capacity = sizeToAllocate / sizeof(T); |
345 } | 345 } |
346 | 346 |
347 void allocateExpandedBuffer(size_t newCapacity) { | 347 void allocateExpandedBuffer(size_t newCapacity) { |
348 ASSERT(newCapacity); | 348 DCHECK(newCapacity); |
349 size_t sizeToAllocate = allocationSize(newCapacity); | 349 size_t sizeToAllocate = allocationSize(newCapacity); |
350 if (hasInlineCapacity) | 350 if (hasInlineCapacity) |
351 m_buffer = | 351 m_buffer = |
352 Allocator::template allocateInlineVectorBacking<T>(sizeToAllocate); | 352 Allocator::template allocateInlineVectorBacking<T>(sizeToAllocate); |
353 else | 353 else |
354 m_buffer = | 354 m_buffer = |
355 Allocator::template allocateExpandedVectorBacking<T>(sizeToAllocate); | 355 Allocator::template allocateExpandedVectorBacking<T>(sizeToAllocate); |
356 m_capacity = sizeToAllocate / sizeof(T); | 356 m_capacity = sizeToAllocate / sizeof(T); |
357 } | 357 } |
358 | 358 |
(...skipping 10 matching lines...) Expand all Loading... |
369 // finalizing, we clear out the unused slots so that the visitor or the | 369 // finalizing, we clear out the unused slots so that the visitor or the |
370 // finalizer does not cause a problem when visiting the unused slots. | 370 // finalizer does not cause a problem when visiting the unused slots. |
371 VectorUnusedSlotClearer< | 371 VectorUnusedSlotClearer< |
372 Allocator::isGarbageCollected && | 372 Allocator::isGarbageCollected && |
373 (VectorTraits<T>::needsDestruction || | 373 (VectorTraits<T>::needsDestruction || |
374 IsTraceableInCollectionTrait<VectorTraits<T>>::value), | 374 IsTraceableInCollectionTrait<VectorTraits<T>>::value), |
375 T>::clear(from, to); | 375 T>::clear(from, to); |
376 } | 376 } |
377 | 377 |
378 void checkUnusedSlots(const T* from, const T* to) { | 378 void checkUnusedSlots(const T* from, const T* to) { |
379 #if ENABLE(ASSERT) && !defined(ANNOTATE_CONTIGUOUS_CONTAINER) | 379 #if DCHECK_IS_ON() && !defined(ANNOTATE_CONTIGUOUS_CONTAINER) |
380 VectorUnusedSlotClearer< | 380 VectorUnusedSlotClearer< |
381 Allocator::isGarbageCollected && | 381 Allocator::isGarbageCollected && |
382 (VectorTraits<T>::needsDestruction || | 382 (VectorTraits<T>::needsDestruction || |
383 IsTraceableInCollectionTrait<VectorTraits<T>>::value), | 383 IsTraceableInCollectionTrait<VectorTraits<T>>::value), |
384 T>::checkCleared(from, to); | 384 T>::checkCleared(from, to); |
385 #endif | 385 #endif |
386 } | 386 } |
387 | 387 |
388 // |end| is exclusive, a la STL. | 388 // |end| is exclusive, a la STL. |
389 struct OffsetRange final { | 389 struct OffsetRange final { |
390 OffsetRange() : begin(0), end(0) {} | 390 OffsetRange() : begin(0), end(0) {} |
391 explicit OffsetRange(size_t begin, size_t end) : begin(begin), end(end) { | 391 explicit OffsetRange(size_t begin, size_t end) : begin(begin), end(end) { |
392 ASSERT(begin <= end); | 392 DCHECK_LE(begin, end); |
393 } | 393 } |
394 bool empty() const { return begin == end; } | 394 bool empty() const { return begin == end; } |
395 size_t begin; | 395 size_t begin; |
396 size_t end; | 396 size_t end; |
397 }; | 397 }; |
398 | 398 |
399 protected: | 399 protected: |
400 VectorBufferBase() : m_buffer(nullptr), m_capacity(0) {} | 400 VectorBufferBase() : m_buffer(nullptr), m_capacity(0) {} |
401 | 401 |
402 VectorBufferBase(T* buffer, size_t capacity) | 402 VectorBufferBase(T* buffer, size_t capacity) |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
442 bool expandBuffer(size_t newCapacity) { | 442 bool expandBuffer(size_t newCapacity) { |
443 size_t sizeToAllocate = allocationSize(newCapacity); | 443 size_t sizeToAllocate = allocationSize(newCapacity); |
444 if (Allocator::expandVectorBacking(m_buffer, sizeToAllocate)) { | 444 if (Allocator::expandVectorBacking(m_buffer, sizeToAllocate)) { |
445 m_capacity = sizeToAllocate / sizeof(T); | 445 m_capacity = sizeToAllocate / sizeof(T); |
446 return true; | 446 return true; |
447 } | 447 } |
448 return false; | 448 return false; |
449 } | 449 } |
450 | 450 |
451 inline bool shrinkBuffer(size_t newCapacity) { | 451 inline bool shrinkBuffer(size_t newCapacity) { |
452 ASSERT(newCapacity < capacity()); | 452 DCHECK_LT(newCapacity, capacity()); |
453 size_t sizeToAllocate = allocationSize(newCapacity); | 453 size_t sizeToAllocate = allocationSize(newCapacity); |
454 if (Allocator::shrinkVectorBacking(m_buffer, allocationSize(capacity()), | 454 if (Allocator::shrinkVectorBacking(m_buffer, allocationSize(capacity()), |
455 sizeToAllocate)) { | 455 sizeToAllocate)) { |
456 m_capacity = sizeToAllocate / sizeof(T); | 456 m_capacity = sizeToAllocate / sizeof(T); |
457 return true; | 457 return true; |
458 } | 458 } |
459 return false; | 459 return false; |
460 } | 460 } |
461 | 461 |
462 void resetBufferPointer() { | 462 void resetBufferPointer() { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 NEVER_INLINE void reallyDeallocateBuffer(T* bufferToDeallocate) { | 528 NEVER_INLINE void reallyDeallocateBuffer(T* bufferToDeallocate) { |
529 Allocator::freeInlineVectorBacking(bufferToDeallocate); | 529 Allocator::freeInlineVectorBacking(bufferToDeallocate); |
530 } | 530 } |
531 | 531 |
532 void deallocateBuffer(T* bufferToDeallocate) { | 532 void deallocateBuffer(T* bufferToDeallocate) { |
533 if (UNLIKELY(bufferToDeallocate != inlineBuffer())) | 533 if (UNLIKELY(bufferToDeallocate != inlineBuffer())) |
534 reallyDeallocateBuffer(bufferToDeallocate); | 534 reallyDeallocateBuffer(bufferToDeallocate); |
535 } | 535 } |
536 | 536 |
537 bool expandBuffer(size_t newCapacity) { | 537 bool expandBuffer(size_t newCapacity) { |
538 ASSERT(newCapacity > inlineCapacity); | 538 DCHECK_GT(newCapacity, inlineCapacity); |
539 if (m_buffer == inlineBuffer()) | 539 if (m_buffer == inlineBuffer()) |
540 return false; | 540 return false; |
541 | 541 |
542 size_t sizeToAllocate = allocationSize(newCapacity); | 542 size_t sizeToAllocate = allocationSize(newCapacity); |
543 if (Allocator::expandInlineVectorBacking(m_buffer, sizeToAllocate)) { | 543 if (Allocator::expandInlineVectorBacking(m_buffer, sizeToAllocate)) { |
544 m_capacity = sizeToAllocate / sizeof(T); | 544 m_capacity = sizeToAllocate / sizeof(T); |
545 return true; | 545 return true; |
546 } | 546 } |
547 return false; | 547 return false; |
548 } | 548 } |
549 | 549 |
550 inline bool shrinkBuffer(size_t newCapacity) { | 550 inline bool shrinkBuffer(size_t newCapacity) { |
551 ASSERT(newCapacity < capacity()); | 551 DCHECK_LT(newCapacity, capacity()); |
552 if (newCapacity <= inlineCapacity) { | 552 if (newCapacity <= inlineCapacity) { |
553 // We need to switch to inlineBuffer. Vector::shrinkCapacity will | 553 // We need to switch to inlineBuffer. Vector::shrinkCapacity will |
554 // handle it. | 554 // handle it. |
555 return false; | 555 return false; |
556 } | 556 } |
557 ASSERT(m_buffer != inlineBuffer()); | 557 DCHECK_NE(m_buffer, inlineBuffer()); |
558 size_t newSize = allocationSize(newCapacity); | 558 size_t newSize = allocationSize(newCapacity); |
559 if (!Allocator::shrinkInlineVectorBacking( | 559 if (!Allocator::shrinkInlineVectorBacking( |
560 m_buffer, allocationSize(capacity()), newSize)) | 560 m_buffer, allocationSize(capacity()), newSize)) |
561 return false; | 561 return false; |
562 m_capacity = newSize / sizeof(T); | 562 m_capacity = newSize / sizeof(T); |
563 return true; | 563 return true; |
564 } | 564 } |
565 | 565 |
566 void resetBufferPointer() { | 566 void resetBufferPointer() { |
567 m_buffer = inlineBuffer(); | 567 m_buffer = inlineBuffer(); |
568 m_capacity = inlineCapacity; | 568 m_capacity = inlineCapacity; |
569 } | 569 } |
570 | 570 |
571 void allocateBuffer(size_t newCapacity) { | 571 void allocateBuffer(size_t newCapacity) { |
572 // FIXME: This should ASSERT(!m_buffer) to catch misuse/leaks. | 572 // FIXME: This should DCHECK(!m_buffer) to catch misuse/leaks. |
573 if (newCapacity > inlineCapacity) | 573 if (newCapacity > inlineCapacity) |
574 Base::allocateBuffer(newCapacity); | 574 Base::allocateBuffer(newCapacity); |
575 else | 575 else |
576 resetBufferPointer(); | 576 resetBufferPointer(); |
577 } | 577 } |
578 | 578 |
579 void allocateExpandedBuffer(size_t newCapacity) { | 579 void allocateExpandedBuffer(size_t newCapacity) { |
580 if (newCapacity > inlineCapacity) | 580 if (newCapacity > inlineCapacity) |
581 Base::allocateExpandedBuffer(newCapacity); | 581 Base::allocateExpandedBuffer(newCapacity); |
582 else | 582 else |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
635 // buffer's inline buffer. Elements in an out-of-line buffer won't move, | 635 // buffer's inline buffer. Elements in an out-of-line buffer won't move, |
636 // because we can just swap pointers of out-of-line buffers. | 636 // because we can just swap pointers of out-of-line buffers. |
637 T* thisSourceBegin = nullptr; | 637 T* thisSourceBegin = nullptr; |
638 size_t thisSourceSize = 0; | 638 size_t thisSourceSize = 0; |
639 T* thisDestinationBegin = nullptr; | 639 T* thisDestinationBegin = nullptr; |
640 if (buffer() == inlineBuffer()) { | 640 if (buffer() == inlineBuffer()) { |
641 thisSourceBegin = buffer(); | 641 thisSourceBegin = buffer(); |
642 thisSourceSize = m_size; | 642 thisSourceSize = m_size; |
643 thisDestinationBegin = other.inlineBuffer(); | 643 thisDestinationBegin = other.inlineBuffer(); |
644 if (!thisHole.empty()) { // Sanity check. | 644 if (!thisHole.empty()) { // Sanity check. |
645 ASSERT(thisHole.begin < thisHole.end); | 645 DCHECK_LT(thisHole.begin, thisHole.end); |
646 ASSERT(thisHole.end <= thisSourceSize); | 646 DCHECK_LE(thisHole.end, thisSourceSize); |
647 } | 647 } |
648 } else { | 648 } else { |
649 // We don't need the hole information for an out-of-line buffer. | 649 // We don't need the hole information for an out-of-line buffer. |
650 thisHole.begin = thisHole.end = 0; | 650 thisHole.begin = thisHole.end = 0; |
651 } | 651 } |
652 T* otherSourceBegin = nullptr; | 652 T* otherSourceBegin = nullptr; |
653 size_t otherSourceSize = 0; | 653 size_t otherSourceSize = 0; |
654 T* otherDestinationBegin = nullptr; | 654 T* otherDestinationBegin = nullptr; |
655 if (other.buffer() == other.inlineBuffer()) { | 655 if (other.buffer() == other.inlineBuffer()) { |
656 otherSourceBegin = other.buffer(); | 656 otherSourceBegin = other.buffer(); |
657 otherSourceSize = other.m_size; | 657 otherSourceSize = other.m_size; |
658 otherDestinationBegin = inlineBuffer(); | 658 otherDestinationBegin = inlineBuffer(); |
659 if (!otherHole.empty()) { | 659 if (!otherHole.empty()) { |
660 ASSERT(otherHole.begin < otherHole.end); | 660 DCHECK_LT(otherHole.begin, otherHole.end); |
661 ASSERT(otherHole.end <= otherSourceSize); | 661 DCHECK_LE(otherHole.end, otherSourceSize); |
662 } | 662 } |
663 } else { | 663 } else { |
664 otherHole.begin = otherHole.end = 0; | 664 otherHole.begin = otherHole.end = 0; |
665 } | 665 } |
666 | 666 |
667 // Next, we mutate members and do other bookkeeping. We do pointer swapping | 667 // Next, we mutate members and do other bookkeeping. We do pointer swapping |
668 // (for out-of-line buffers) here if we can. From now on, don't assume | 668 // (for out-of-line buffers) here if we can. From now on, don't assume |
669 // buffer() or capacity() maintains their original values. | 669 // buffer() or capacity() maintains their original values. |
670 std::swap(m_capacity, other.m_capacity); | 670 std::swap(m_capacity, other.m_capacity); |
671 if (thisSourceBegin && | 671 if (thisSourceBegin && |
672 !otherSourceBegin) { // Our buffer is inline, theirs is not. | 672 !otherSourceBegin) { // Our buffer is inline, theirs is not. |
673 ASSERT(buffer() == inlineBuffer()); | 673 DCHECK_EQ(buffer(), inlineBuffer()); |
674 ASSERT(other.buffer() != other.inlineBuffer()); | 674 DCHECK_NE(other.buffer(), other.inlineBuffer()); |
675 ANNOTATE_DELETE_BUFFER(m_buffer, inlineCapacity, m_size); | 675 ANNOTATE_DELETE_BUFFER(m_buffer, inlineCapacity, m_size); |
676 m_buffer = other.buffer(); | 676 m_buffer = other.buffer(); |
677 other.m_buffer = other.inlineBuffer(); | 677 other.m_buffer = other.inlineBuffer(); |
678 std::swap(m_size, other.m_size); | 678 std::swap(m_size, other.m_size); |
679 ANNOTATE_NEW_BUFFER(other.m_buffer, inlineCapacity, other.m_size); | 679 ANNOTATE_NEW_BUFFER(other.m_buffer, inlineCapacity, other.m_size); |
680 } else if (!thisSourceBegin && | 680 } else if (!thisSourceBegin && |
681 otherSourceBegin) { // Their buffer is inline, ours is not. | 681 otherSourceBegin) { // Their buffer is inline, ours is not. |
682 ASSERT(buffer() != inlineBuffer()); | 682 DCHECK_NE(buffer(), inlineBuffer()); |
683 ASSERT(other.buffer() == other.inlineBuffer()); | 683 DCHECK_EQ(other.buffer(), other.inlineBuffer()); |
684 ANNOTATE_DELETE_BUFFER(other.m_buffer, inlineCapacity, other.m_size); | 684 ANNOTATE_DELETE_BUFFER(other.m_buffer, inlineCapacity, other.m_size); |
685 other.m_buffer = buffer(); | 685 other.m_buffer = buffer(); |
686 m_buffer = inlineBuffer(); | 686 m_buffer = inlineBuffer(); |
687 std::swap(m_size, other.m_size); | 687 std::swap(m_size, other.m_size); |
688 ANNOTATE_NEW_BUFFER(m_buffer, inlineCapacity, m_size); | 688 ANNOTATE_NEW_BUFFER(m_buffer, inlineCapacity, m_size); |
689 } else { // Both buffers are inline. | 689 } else { // Both buffers are inline. |
690 ASSERT(thisSourceBegin && otherSourceBegin); | 690 DCHECK(thisSourceBegin); |
691 ASSERT(buffer() == inlineBuffer()); | 691 DCHECK(otherSourceBegin); |
692 ASSERT(other.buffer() == other.inlineBuffer()); | 692 DCHECK_EQ(buffer(), inlineBuffer()); |
| 693 DCHECK_EQ(other.buffer(), other.inlineBuffer()); |
693 ANNOTATE_CHANGE_SIZE(m_buffer, inlineCapacity, m_size, other.m_size); | 694 ANNOTATE_CHANGE_SIZE(m_buffer, inlineCapacity, m_size, other.m_size); |
694 ANNOTATE_CHANGE_SIZE(other.m_buffer, inlineCapacity, other.m_size, | 695 ANNOTATE_CHANGE_SIZE(other.m_buffer, inlineCapacity, other.m_size, |
695 m_size); | 696 m_size); |
696 std::swap(m_size, other.m_size); | 697 std::swap(m_size, other.m_size); |
697 } | 698 } |
698 | 699 |
699 // We are ready to move elements. We determine an action for each "section", | 700 // We are ready to move elements. We determine an action for each "section", |
700 // which is a contiguous range such that all elements in the range are | 701 // which is a contiguous range such that all elements in the range are |
701 // treated similarly. | 702 // treated similarly. |
702 size_t sectionBegin = 0; | 703 size_t sectionBegin = 0; |
703 while (sectionBegin < inlineCapacity) { | 704 while (sectionBegin < inlineCapacity) { |
704 // To determine the end of this section, we list up all the boundaries | 705 // To determine the end of this section, we list up all the boundaries |
705 // where the "occupiedness" may change. | 706 // where the "occupiedness" may change. |
706 size_t sectionEnd = inlineCapacity; | 707 size_t sectionEnd = inlineCapacity; |
707 if (thisSourceBegin && sectionBegin < thisSourceSize) | 708 if (thisSourceBegin && sectionBegin < thisSourceSize) |
708 sectionEnd = std::min(sectionEnd, thisSourceSize); | 709 sectionEnd = std::min(sectionEnd, thisSourceSize); |
709 if (!thisHole.empty() && sectionBegin < thisHole.begin) | 710 if (!thisHole.empty() && sectionBegin < thisHole.begin) |
710 sectionEnd = std::min(sectionEnd, thisHole.begin); | 711 sectionEnd = std::min(sectionEnd, thisHole.begin); |
711 if (!thisHole.empty() && sectionBegin < thisHole.end) | 712 if (!thisHole.empty() && sectionBegin < thisHole.end) |
712 sectionEnd = std::min(sectionEnd, thisHole.end); | 713 sectionEnd = std::min(sectionEnd, thisHole.end); |
713 if (otherSourceBegin && sectionBegin < otherSourceSize) | 714 if (otherSourceBegin && sectionBegin < otherSourceSize) |
714 sectionEnd = std::min(sectionEnd, otherSourceSize); | 715 sectionEnd = std::min(sectionEnd, otherSourceSize); |
715 if (!otherHole.empty() && sectionBegin < otherHole.begin) | 716 if (!otherHole.empty() && sectionBegin < otherHole.begin) |
716 sectionEnd = std::min(sectionEnd, otherHole.begin); | 717 sectionEnd = std::min(sectionEnd, otherHole.begin); |
717 if (!otherHole.empty() && sectionBegin < otherHole.end) | 718 if (!otherHole.empty() && sectionBegin < otherHole.end) |
718 sectionEnd = std::min(sectionEnd, otherHole.end); | 719 sectionEnd = std::min(sectionEnd, otherHole.end); |
719 | 720 |
720 ASSERT(sectionBegin < sectionEnd); | 721 DCHECK_LT(sectionBegin, sectionEnd); |
721 | 722 |
722 // Is the |sectionBegin|-th element of |thisSource| occupied? | 723 // Is the |sectionBegin|-th element of |thisSource| occupied? |
723 bool thisOccupied = false; | 724 bool thisOccupied = false; |
724 if (thisSourceBegin && sectionBegin < thisSourceSize) { | 725 if (thisSourceBegin && sectionBegin < thisSourceSize) { |
725 // Yes, it's occupied, unless the position is in a hole. | 726 // Yes, it's occupied, unless the position is in a hole. |
726 if (thisHole.empty() || sectionBegin < thisHole.begin || | 727 if (thisHole.empty() || sectionBegin < thisHole.begin || |
727 sectionBegin >= thisHole.end) | 728 sectionBegin >= thisHole.end) |
728 thisOccupied = true; | 729 thisOccupied = true; |
729 } | 730 } |
730 bool otherOccupied = false; | 731 bool otherOccupied = false; |
731 if (otherSourceBegin && sectionBegin < otherSourceSize) { | 732 if (otherSourceBegin && sectionBegin < otherSourceSize) { |
732 if (otherHole.empty() || sectionBegin < otherHole.begin || | 733 if (otherHole.empty() || sectionBegin < otherHole.begin || |
733 sectionBegin >= otherHole.end) | 734 sectionBegin >= otherHole.end) |
734 otherOccupied = true; | 735 otherOccupied = true; |
735 } | 736 } |
736 | 737 |
737 if (thisOccupied && otherOccupied) { | 738 if (thisOccupied && otherOccupied) { |
738 // Both occupied; swap them. In this case, one's destination must be the | 739 // Both occupied; swap them. In this case, one's destination must be the |
739 // other's source (i.e. both ranges are in inline buffers). | 740 // other's source (i.e. both ranges are in inline buffers). |
740 ASSERT(thisDestinationBegin == otherSourceBegin); | 741 DCHECK_EQ(thisDestinationBegin, otherSourceBegin); |
741 ASSERT(otherDestinationBegin == thisSourceBegin); | 742 DCHECK_EQ(otherDestinationBegin, thisSourceBegin); |
742 TypeOperations::swap(thisSourceBegin + sectionBegin, | 743 TypeOperations::swap(thisSourceBegin + sectionBegin, |
743 thisSourceBegin + sectionEnd, | 744 thisSourceBegin + sectionEnd, |
744 otherSourceBegin + sectionBegin); | 745 otherSourceBegin + sectionBegin); |
745 } else if (thisOccupied) { | 746 } else if (thisOccupied) { |
746 // Move from ours to theirs. | 747 // Move from ours to theirs. |
747 TypeOperations::move(thisSourceBegin + sectionBegin, | 748 TypeOperations::move(thisSourceBegin + sectionBegin, |
748 thisSourceBegin + sectionEnd, | 749 thisSourceBegin + sectionEnd, |
749 thisDestinationBegin + sectionBegin); | 750 thisDestinationBegin + sectionBegin); |
750 Base::clearUnusedSlots(thisSourceBegin + sectionBegin, | 751 Base::clearUnusedSlots(thisSourceBegin + sectionBegin, |
751 thisSourceBegin + sectionEnd); | 752 thisSourceBegin + sectionEnd); |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
969 void prepend(const U*, size_t); | 970 void prepend(const U*, size_t); |
970 template <typename U> | 971 template <typename U> |
971 void prepend(U&&); | 972 void prepend(U&&); |
972 template <typename U, size_t c, typename V> | 973 template <typename U, size_t c, typename V> |
973 void prependVector(const Vector<U, c, V>&); | 974 void prependVector(const Vector<U, c, V>&); |
974 | 975 |
975 void remove(size_t position); | 976 void remove(size_t position); |
976 void remove(size_t position, size_t length); | 977 void remove(size_t position, size_t length); |
977 | 978 |
978 void pop_back() { | 979 void pop_back() { |
979 ASSERT(!isEmpty()); | 980 DCHECK(!isEmpty()); |
980 shrink(size() - 1); | 981 shrink(size() - 1); |
981 } | 982 } |
982 | 983 |
983 Vector(size_t size, const T& val) : Base(size) { | 984 Vector(size_t size, const T& val) : Base(size) { |
984 ANNOTATE_NEW_BUFFER(begin(), capacity(), size); | 985 ANNOTATE_NEW_BUFFER(begin(), capacity(), size); |
985 m_size = size; | 986 m_size = size; |
986 TypeOperations::uninitializedFill(begin(), end(), val); | 987 TypeOperations::uninitializedFill(begin(), end(), val); |
987 } | 988 } |
988 | 989 |
989 void fill(const T&, size_t); | 990 void fill(const T&, size_t); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1055 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>:: | 1056 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>:: |
1056 operator=(const Vector<T, inlineCapacity, Allocator>& other) { | 1057 operator=(const Vector<T, inlineCapacity, Allocator>& other) { |
1057 if (UNLIKELY(&other == this)) | 1058 if (UNLIKELY(&other == this)) |
1058 return *this; | 1059 return *this; |
1059 | 1060 |
1060 if (size() > other.size()) { | 1061 if (size() > other.size()) { |
1061 shrink(other.size()); | 1062 shrink(other.size()); |
1062 } else if (other.size() > capacity()) { | 1063 } else if (other.size() > capacity()) { |
1063 clear(); | 1064 clear(); |
1064 reserveCapacity(other.size()); | 1065 reserveCapacity(other.size()); |
1065 ASSERT(begin()); | 1066 DCHECK(begin()); |
1066 } | 1067 } |
1067 | 1068 |
1068 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, other.size()); | 1069 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, other.size()); |
1069 std::copy(other.begin(), other.begin() + size(), begin()); | 1070 std::copy(other.begin(), other.begin() + size(), begin()); |
1070 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end()); | 1071 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end()); |
1071 m_size = other.size(); | 1072 m_size = other.size(); |
1072 | 1073 |
1073 return *this; | 1074 return *this; |
1074 } | 1075 } |
1075 | 1076 |
1076 inline bool typelessPointersAreEqual(const void* a, const void* b) { | 1077 inline bool typelessPointersAreEqual(const void* a, const void* b) { |
1077 return a == b; | 1078 return a == b; |
1078 } | 1079 } |
1079 | 1080 |
1080 template <typename T, size_t inlineCapacity, typename Allocator> | 1081 template <typename T, size_t inlineCapacity, typename Allocator> |
1081 template <size_t otherCapacity> | 1082 template <size_t otherCapacity> |
1082 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>:: | 1083 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>:: |
1083 operator=(const Vector<T, otherCapacity, Allocator>& other) { | 1084 operator=(const Vector<T, otherCapacity, Allocator>& other) { |
1084 // If the inline capacities match, we should call the more specific | 1085 // If the inline capacities match, we should call the more specific |
1085 // template. If the inline capacities don't match, the two objects | 1086 // template. If the inline capacities don't match, the two objects |
1086 // shouldn't be allocated the same address. | 1087 // shouldn't be allocated the same address. |
1087 ASSERT(!typelessPointersAreEqual(&other, this)); | 1088 DCHECK(!typelessPointersAreEqual(&other, this)); |
1088 | 1089 |
1089 if (size() > other.size()) { | 1090 if (size() > other.size()) { |
1090 shrink(other.size()); | 1091 shrink(other.size()); |
1091 } else if (other.size() > capacity()) { | 1092 } else if (other.size() > capacity()) { |
1092 clear(); | 1093 clear(); |
1093 reserveCapacity(other.size()); | 1094 reserveCapacity(other.size()); |
1094 ASSERT(begin()); | 1095 DCHECK(begin()); |
1095 } | 1096 } |
1096 | 1097 |
1097 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, other.size()); | 1098 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, other.size()); |
1098 std::copy(other.begin(), other.begin() + size(), begin()); | 1099 std::copy(other.begin(), other.begin() + size(), begin()); |
1099 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end()); | 1100 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end()); |
1100 m_size = other.size(); | 1101 m_size = other.size(); |
1101 | 1102 |
1102 return *this; | 1103 return *this; |
1103 } | 1104 } |
1104 | 1105 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1177 return kNotFound; | 1178 return kNotFound; |
1178 } | 1179 } |
1179 | 1180 |
1180 template <typename T, size_t inlineCapacity, typename Allocator> | 1181 template <typename T, size_t inlineCapacity, typename Allocator> |
1181 void Vector<T, inlineCapacity, Allocator>::fill(const T& val, size_t newSize) { | 1182 void Vector<T, inlineCapacity, Allocator>::fill(const T& val, size_t newSize) { |
1182 if (size() > newSize) { | 1183 if (size() > newSize) { |
1183 shrink(newSize); | 1184 shrink(newSize); |
1184 } else if (newSize > capacity()) { | 1185 } else if (newSize > capacity()) { |
1185 clear(); | 1186 clear(); |
1186 reserveCapacity(newSize); | 1187 reserveCapacity(newSize); |
1187 ASSERT(begin()); | 1188 DCHECK(begin()); |
1188 } | 1189 } |
1189 | 1190 |
1190 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize); | 1191 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize); |
1191 std::fill(begin(), end(), val); | 1192 std::fill(begin(), end(), val); |
1192 TypeOperations::uninitializedFill(end(), begin() + newSize, val); | 1193 TypeOperations::uninitializedFill(end(), begin() + newSize, val); |
1193 m_size = newSize; | 1194 m_size = newSize; |
1194 } | 1195 } |
1195 | 1196 |
1196 template <typename T, size_t inlineCapacity, typename Allocator> | 1197 template <typename T, size_t inlineCapacity, typename Allocator> |
1197 template <typename Iterator> | 1198 template <typename Iterator> |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1261 expandCapacity(size); | 1262 expandCapacity(size); |
1262 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size); | 1263 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size); |
1263 TypeOperations::initialize(end(), begin() + size); | 1264 TypeOperations::initialize(end(), begin() + size); |
1264 } | 1265 } |
1265 | 1266 |
1266 m_size = size; | 1267 m_size = size; |
1267 } | 1268 } |
1268 | 1269 |
1269 template <typename T, size_t inlineCapacity, typename Allocator> | 1270 template <typename T, size_t inlineCapacity, typename Allocator> |
1270 void Vector<T, inlineCapacity, Allocator>::shrink(size_t size) { | 1271 void Vector<T, inlineCapacity, Allocator>::shrink(size_t size) { |
1271 ASSERT(size <= m_size); | 1272 DCHECK_LE(size, m_size); |
1272 TypeOperations::destruct(begin() + size, end()); | 1273 TypeOperations::destruct(begin() + size, end()); |
1273 clearUnusedSlots(begin() + size, end()); | 1274 clearUnusedSlots(begin() + size, end()); |
1274 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size); | 1275 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size); |
1275 m_size = size; | 1276 m_size = size; |
1276 } | 1277 } |
1277 | 1278 |
1278 template <typename T, size_t inlineCapacity, typename Allocator> | 1279 template <typename T, size_t inlineCapacity, typename Allocator> |
1279 void Vector<T, inlineCapacity, Allocator>::grow(size_t size) { | 1280 void Vector<T, inlineCapacity, Allocator>::grow(size_t size) { |
1280 ASSERT(size >= m_size); | 1281 DCHECK_GE(size, m_size); |
1281 if (size > capacity()) | 1282 if (size > capacity()) |
1282 expandCapacity(size); | 1283 expandCapacity(size); |
1283 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size); | 1284 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size); |
1284 TypeOperations::initialize(end(), begin() + size); | 1285 TypeOperations::initialize(end(), begin() + size); |
1285 m_size = size; | 1286 m_size = size; |
1286 } | 1287 } |
1287 | 1288 |
1288 template <typename T, size_t inlineCapacity, typename Allocator> | 1289 template <typename T, size_t inlineCapacity, typename Allocator> |
1289 void Vector<T, inlineCapacity, Allocator>::reserveCapacity(size_t newCapacity) { | 1290 void Vector<T, inlineCapacity, Allocator>::reserveCapacity(size_t newCapacity) { |
1290 if (UNLIKELY(newCapacity <= capacity())) | 1291 if (UNLIKELY(newCapacity <= capacity())) |
(...skipping 18 matching lines...) Expand all Loading... |
1309 ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size); | 1310 ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size); |
1310 TypeOperations::move(oldBuffer, oldEnd, begin()); | 1311 TypeOperations::move(oldBuffer, oldEnd, begin()); |
1311 clearUnusedSlots(oldBuffer, oldEnd); | 1312 clearUnusedSlots(oldBuffer, oldEnd); |
1312 ANNOTATE_DELETE_BUFFER(oldBuffer, oldCapacity, m_size); | 1313 ANNOTATE_DELETE_BUFFER(oldBuffer, oldCapacity, m_size); |
1313 Base::deallocateBuffer(oldBuffer); | 1314 Base::deallocateBuffer(oldBuffer); |
1314 } | 1315 } |
1315 | 1316 |
1316 template <typename T, size_t inlineCapacity, typename Allocator> | 1317 template <typename T, size_t inlineCapacity, typename Allocator> |
1317 inline void Vector<T, inlineCapacity, Allocator>::reserveInitialCapacity( | 1318 inline void Vector<T, inlineCapacity, Allocator>::reserveInitialCapacity( |
1318 size_t initialCapacity) { | 1319 size_t initialCapacity) { |
1319 ASSERT(!m_size); | 1320 DCHECK(!m_size); |
1320 ASSERT(capacity() == INLINE_CAPACITY); | 1321 DCHECK(capacity() == INLINE_CAPACITY); |
1321 if (initialCapacity > INLINE_CAPACITY) { | 1322 if (initialCapacity > INLINE_CAPACITY) { |
1322 ANNOTATE_DELETE_BUFFER(begin(), capacity(), m_size); | 1323 ANNOTATE_DELETE_BUFFER(begin(), capacity(), m_size); |
1323 Base::allocateBuffer(initialCapacity); | 1324 Base::allocateBuffer(initialCapacity); |
1324 ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size); | 1325 ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size); |
1325 } | 1326 } |
1326 } | 1327 } |
1327 | 1328 |
1328 template <typename T, size_t inlineCapacity, typename Allocator> | 1329 template <typename T, size_t inlineCapacity, typename Allocator> |
1329 void Vector<T, inlineCapacity, Allocator>::shrinkCapacity(size_t newCapacity) { | 1330 void Vector<T, inlineCapacity, Allocator>::shrinkCapacity(size_t newCapacity) { |
1330 if (newCapacity >= capacity()) | 1331 if (newCapacity >= capacity()) |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1365 } | 1366 } |
1366 | 1367 |
1367 // Templatizing these is better than just letting the conversion happen | 1368 // Templatizing these is better than just letting the conversion happen |
1368 // implicitly, because for instance it allows a PassRefPtr to be appended to a | 1369 // implicitly, because for instance it allows a PassRefPtr to be appended to a |
1369 // RefPtr vector without refcount thrash. | 1370 // RefPtr vector without refcount thrash. |
1370 | 1371 |
1371 template <typename T, size_t inlineCapacity, typename Allocator> | 1372 template <typename T, size_t inlineCapacity, typename Allocator> |
1372 template <typename U> | 1373 template <typename U> |
1373 void Vector<T, inlineCapacity, Allocator>::append(const U* data, | 1374 void Vector<T, inlineCapacity, Allocator>::append(const U* data, |
1374 size_t dataSize) { | 1375 size_t dataSize) { |
1375 ASSERT(Allocator::isAllocationAllowed()); | 1376 DCHECK(Allocator::isAllocationAllowed()); |
1376 size_t newSize = m_size + dataSize; | 1377 size_t newSize = m_size + dataSize; |
1377 if (newSize > capacity()) { | 1378 if (newSize > capacity()) { |
1378 data = expandCapacity(newSize, data); | 1379 data = expandCapacity(newSize, data); |
1379 ASSERT(begin()); | 1380 DCHECK(begin()); |
1380 } | 1381 } |
1381 RELEASE_ASSERT(newSize >= m_size); | 1382 RELEASE_ASSERT(newSize >= m_size); |
1382 T* dest = end(); | 1383 T* dest = end(); |
1383 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize); | 1384 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize); |
1384 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy( | 1385 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy( |
1385 data, &data[dataSize], dest); | 1386 data, &data[dataSize], dest); |
1386 m_size = newSize; | 1387 m_size = newSize; |
1387 } | 1388 } |
1388 | 1389 |
1389 template <typename T, size_t inlineCapacity, typename Allocator> | 1390 template <typename T, size_t inlineCapacity, typename Allocator> |
1390 template <typename U> | 1391 template <typename U> |
1391 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::push_back(U&& val) { | 1392 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::push_back(U&& val) { |
1392 return append(std::forward<U>(val)); | 1393 return append(std::forward<U>(val)); |
1393 } | 1394 } |
1394 | 1395 |
1395 template <typename T, size_t inlineCapacity, typename Allocator> | 1396 template <typename T, size_t inlineCapacity, typename Allocator> |
1396 template <typename U> | 1397 template <typename U> |
1397 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::append(U&& val) { | 1398 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::append(U&& val) { |
1398 ASSERT(Allocator::isAllocationAllowed()); | 1399 DCHECK(Allocator::isAllocationAllowed()); |
1399 if (LIKELY(size() != capacity())) { | 1400 if (LIKELY(size() != capacity())) { |
1400 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); | 1401 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); |
1401 new (NotNull, end()) T(std::forward<U>(val)); | 1402 new (NotNull, end()) T(std::forward<U>(val)); |
1402 ++m_size; | 1403 ++m_size; |
1403 return; | 1404 return; |
1404 } | 1405 } |
1405 | 1406 |
1406 appendSlowCase(std::forward<U>(val)); | 1407 appendSlowCase(std::forward<U>(val)); |
1407 } | 1408 } |
1408 | 1409 |
(...skipping 11 matching lines...) Expand all Loading... |
1420 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); | 1421 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); |
1421 T* t = new (NotNull, end()) T(std::forward<Args>(args)...); | 1422 T* t = new (NotNull, end()) T(std::forward<Args>(args)...); |
1422 ++m_size; | 1423 ++m_size; |
1423 return *t; | 1424 return *t; |
1424 } | 1425 } |
1425 | 1426 |
1426 template <typename T, size_t inlineCapacity, typename Allocator> | 1427 template <typename T, size_t inlineCapacity, typename Allocator> |
1427 template <typename U> | 1428 template <typename U> |
1428 NEVER_INLINE void Vector<T, inlineCapacity, Allocator>::appendSlowCase( | 1429 NEVER_INLINE void Vector<T, inlineCapacity, Allocator>::appendSlowCase( |
1429 U&& val) { | 1430 U&& val) { |
1430 ASSERT(size() == capacity()); | 1431 DCHECK_EQ(size(), capacity()); |
1431 | 1432 |
1432 typename std::remove_reference<U>::type* ptr = &val; | 1433 typename std::remove_reference<U>::type* ptr = &val; |
1433 ptr = expandCapacity(size() + 1, ptr); | 1434 ptr = expandCapacity(size() + 1, ptr); |
1434 ASSERT(begin()); | 1435 DCHECK(begin()); |
1435 | 1436 |
1436 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); | 1437 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); |
1437 new (NotNull, end()) T(std::forward<U>(*ptr)); | 1438 new (NotNull, end()) T(std::forward<U>(*ptr)); |
1438 ++m_size; | 1439 ++m_size; |
1439 } | 1440 } |
1440 | 1441 |
1441 // This version of append saves a branch in the case where you know that the | 1442 // This version of append saves a branch in the case where you know that the |
1442 // vector's capacity is large enough for the append to succeed. | 1443 // vector's capacity is large enough for the append to succeed. |
1443 | 1444 |
1444 template <typename T, size_t inlineCapacity, typename Allocator> | 1445 template <typename T, size_t inlineCapacity, typename Allocator> |
1445 template <typename U> | 1446 template <typename U> |
1446 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::uncheckedAppend( | 1447 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::uncheckedAppend( |
1447 U&& val) { | 1448 U&& val) { |
1448 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER | 1449 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER |
1449 // Vectors in ASAN builds don't have inlineCapacity. | 1450 // Vectors in ASAN builds don't have inlineCapacity. |
1450 append(std::forward<U>(val)); | 1451 append(std::forward<U>(val)); |
1451 #else | 1452 #else |
1452 ASSERT(size() < capacity()); | 1453 DCHECK_LT(size(), capacity()); |
1453 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); | 1454 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); |
1454 new (NotNull, end()) T(std::forward<U>(val)); | 1455 new (NotNull, end()) T(std::forward<U>(val)); |
1455 ++m_size; | 1456 ++m_size; |
1456 #endif | 1457 #endif |
1457 } | 1458 } |
1458 | 1459 |
1459 template <typename T, size_t inlineCapacity, typename Allocator> | 1460 template <typename T, size_t inlineCapacity, typename Allocator> |
1460 template <typename U, size_t otherCapacity, typename OtherAllocator> | 1461 template <typename U, size_t otherCapacity, typename OtherAllocator> |
1461 inline void Vector<T, inlineCapacity, Allocator>::appendVector( | 1462 inline void Vector<T, inlineCapacity, Allocator>::appendVector( |
1462 const Vector<U, otherCapacity, OtherAllocator>& val) { | 1463 const Vector<U, otherCapacity, OtherAllocator>& val) { |
1463 append(val.begin(), val.size()); | 1464 append(val.begin(), val.size()); |
1464 } | 1465 } |
1465 | 1466 |
1466 template <typename T, size_t inlineCapacity, typename Allocator> | 1467 template <typename T, size_t inlineCapacity, typename Allocator> |
1467 template <typename U> | 1468 template <typename U> |
1468 void Vector<T, inlineCapacity, Allocator>::insert(size_t position, | 1469 void Vector<T, inlineCapacity, Allocator>::insert(size_t position, |
1469 const U* data, | 1470 const U* data, |
1470 size_t dataSize) { | 1471 size_t dataSize) { |
1471 ASSERT(Allocator::isAllocationAllowed()); | 1472 DCHECK(Allocator::isAllocationAllowed()); |
1472 RELEASE_ASSERT(position <= size()); | 1473 RELEASE_ASSERT(position <= size()); |
1473 size_t newSize = m_size + dataSize; | 1474 size_t newSize = m_size + dataSize; |
1474 if (newSize > capacity()) { | 1475 if (newSize > capacity()) { |
1475 data = expandCapacity(newSize, data); | 1476 data = expandCapacity(newSize, data); |
1476 ASSERT(begin()); | 1477 DCHECK(begin()); |
1477 } | 1478 } |
1478 RELEASE_ASSERT(newSize >= m_size); | 1479 RELEASE_ASSERT(newSize >= m_size); |
1479 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize); | 1480 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize); |
1480 T* spot = begin() + position; | 1481 T* spot = begin() + position; |
1481 TypeOperations::moveOverlapping(spot, end(), spot + dataSize); | 1482 TypeOperations::moveOverlapping(spot, end(), spot + dataSize); |
1482 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy( | 1483 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy( |
1483 data, &data[dataSize], spot); | 1484 data, &data[dataSize], spot); |
1484 m_size = newSize; | 1485 m_size = newSize; |
1485 } | 1486 } |
1486 | 1487 |
1487 template <typename T, size_t inlineCapacity, typename Allocator> | 1488 template <typename T, size_t inlineCapacity, typename Allocator> |
1488 template <typename U> | 1489 template <typename U> |
1489 inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, | 1490 inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, |
1490 U&& val) { | 1491 U&& val) { |
1491 ASSERT(Allocator::isAllocationAllowed()); | 1492 DCHECK(Allocator::isAllocationAllowed()); |
1492 RELEASE_ASSERT(position <= size()); | 1493 RELEASE_ASSERT(position <= size()); |
1493 typename std::remove_reference<U>::type* data = &val; | 1494 typename std::remove_reference<U>::type* data = &val; |
1494 if (size() == capacity()) { | 1495 if (size() == capacity()) { |
1495 data = expandCapacity(size() + 1, data); | 1496 data = expandCapacity(size() + 1, data); |
1496 ASSERT(begin()); | 1497 DCHECK(begin()); |
1497 } | 1498 } |
1498 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); | 1499 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1); |
1499 T* spot = begin() + position; | 1500 T* spot = begin() + position; |
1500 TypeOperations::moveOverlapping(spot, end(), spot + 1); | 1501 TypeOperations::moveOverlapping(spot, end(), spot + 1); |
1501 new (NotNull, spot) T(std::forward<U>(*data)); | 1502 new (NotNull, spot) T(std::forward<U>(*data)); |
1502 ++m_size; | 1503 ++m_size; |
1503 } | 1504 } |
1504 | 1505 |
1505 template <typename T, size_t inlineCapacity, typename Allocator> | 1506 template <typename T, size_t inlineCapacity, typename Allocator> |
1506 template <typename U, size_t c, typename OtherAllocator> | 1507 template <typename U, size_t c, typename OtherAllocator> |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1589 inline bool operator!=(const Vector<T, inlineCapacityA, Allocator>& a, | 1590 inline bool operator!=(const Vector<T, inlineCapacityA, Allocator>& a, |
1590 const Vector<T, inlineCapacityB, Allocator>& b) { | 1591 const Vector<T, inlineCapacityB, Allocator>& b) { |
1591 return !(a == b); | 1592 return !(a == b); |
1592 } | 1593 } |
1593 | 1594 |
1594 // This is only called if the allocator is a HeapAllocator. It is used when | 1595 // This is only called if the allocator is a HeapAllocator. It is used when |
1595 // visiting during a tracing GC. | 1596 // visiting during a tracing GC. |
1596 template <typename T, size_t inlineCapacity, typename Allocator> | 1597 template <typename T, size_t inlineCapacity, typename Allocator> |
1597 template <typename VisitorDispatcher> | 1598 template <typename VisitorDispatcher> |
1598 void Vector<T, inlineCapacity, Allocator>::trace(VisitorDispatcher visitor) { | 1599 void Vector<T, inlineCapacity, Allocator>::trace(VisitorDispatcher visitor) { |
1599 ASSERT(Allocator::isGarbageCollected); // Garbage collector must be enabled. | 1600 DCHECK(Allocator::isGarbageCollected) << "Garbage collector must be enabled."; |
1600 if (!buffer()) | 1601 if (!buffer()) |
1601 return; | 1602 return; |
1602 if (this->hasOutOfLineBuffer()) { | 1603 if (this->hasOutOfLineBuffer()) { |
1603 // This is a performance optimization for a case where the buffer has | 1604 // This is a performance optimization for a case where the buffer has |
1604 // been already traced by somewhere. This can happen if the conservative | 1605 // been already traced by somewhere. This can happen if the conservative |
1605 // scanning traced an on-stack (false-positive or real) pointer to the | 1606 // scanning traced an on-stack (false-positive or real) pointer to the |
1606 // HeapVector, and then visitor->trace() traces the HeapVector. | 1607 // HeapVector, and then visitor->trace() traces the HeapVector. |
1607 if (Allocator::isHeapObjectAlive(buffer())) | 1608 if (Allocator::isHeapObjectAlive(buffer())) |
1608 return; | 1609 return; |
1609 Allocator::markNoTracing(visitor, buffer()); | 1610 Allocator::markNoTracing(visitor, buffer()); |
1610 Allocator::registerBackingStoreReference(visitor, Base::bufferSlot()); | 1611 Allocator::registerBackingStoreReference(visitor, Base::bufferSlot()); |
1611 } | 1612 } |
1612 const T* bufferBegin = buffer(); | 1613 const T* bufferBegin = buffer(); |
1613 const T* bufferEnd = buffer() + size(); | 1614 const T* bufferEnd = buffer() + size(); |
1614 if (IsTraceableInCollectionTrait<VectorTraits<T>>::value) { | 1615 if (IsTraceableInCollectionTrait<VectorTraits<T>>::value) { |
1615 for (const T* bufferEntry = bufferBegin; bufferEntry != bufferEnd; | 1616 for (const T* bufferEntry = bufferBegin; bufferEntry != bufferEnd; |
1616 bufferEntry++) | 1617 bufferEntry++) |
1617 Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>( | 1618 Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>( |
1618 visitor, *const_cast<T*>(bufferEntry)); | 1619 visitor, *const_cast<T*>(bufferEntry)); |
1619 checkUnusedSlots(buffer() + size(), buffer() + capacity()); | 1620 checkUnusedSlots(buffer() + size(), buffer() + capacity()); |
1620 } | 1621 } |
1621 } | 1622 } |
1622 | 1623 |
1623 } // namespace WTF | 1624 } // namespace WTF |
1624 | 1625 |
1625 using WTF::Vector; | 1626 using WTF::Vector; |
1626 | 1627 |
1627 #endif // WTF_Vector_h | 1628 #endif // WTF_Vector_h |
OLD | NEW |