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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 cur->~T(); | 72 cur->~T(); |
73 } | 73 } |
74 }; | 74 }; |
75 | 75 |
76 template <bool unusedSlotsMustBeZeroed, typename T> | 76 template <bool unusedSlotsMustBeZeroed, typename T> |
77 struct VectorUnusedSlotClearer; | 77 struct VectorUnusedSlotClearer; |
78 | 78 |
79 template<typename T> | 79 template<typename T> |
80 struct VectorUnusedSlotClearer<false, T> { | 80 struct VectorUnusedSlotClearer<false, T> { |
81 static void clear(T*, T*) { } | 81 static void clear(T*, T*) { } |
| 82 #if ENABLE(ASSERT) |
| 83 static void checkCleared(const T*, const T*) { } |
| 84 #endif |
82 }; | 85 }; |
83 | 86 |
84 template<typename T> | 87 template<typename T> |
85 struct VectorUnusedSlotClearer<true, T> { | 88 struct VectorUnusedSlotClearer<true, T> { |
86 static void clear(T* begin, T* end) | 89 static void clear(T* begin, T* end) |
87 { | 90 { |
88 // We clear out unused slots so that the visitor and the finalizer | 91 // We clear out unused slots so that the visitor and the finalizer |
89 // do not visit them (or at least it does not matter if they do). | 92 // do not visit them (or at least it does not matter if they do). |
90 memset(begin, 0, sizeof(T) * (end - begin)); | 93 memset(begin, 0, sizeof(T) * (end - begin)); |
91 } | 94 } |
| 95 |
| 96 #if ENABLE(ASSERT) |
| 97 static void checkCleared(const T* begin, const T* end) |
| 98 { |
| 99 const unsigned char* unusedArea = reinterpret_cast<const unsigned ch
ar*>(begin); |
| 100 const unsigned char* endAddress = reinterpret_cast<const unsigned ch
ar*>(end); |
| 101 ASSERT(endAddress >= unusedArea); |
| 102 for (int i = 0; i < endAddress - unusedArea; ++i) |
| 103 ASSERT(!unusedArea[i]); |
| 104 } |
| 105 #endif |
92 }; | 106 }; |
93 | 107 |
94 template <bool canInitializeWithMemset, typename T> | 108 template <bool canInitializeWithMemset, typename T> |
95 struct VectorInitializer; | 109 struct VectorInitializer; |
96 | 110 |
97 template<typename T> | 111 template<typename T> |
98 struct VectorInitializer<false, T> | 112 struct VectorInitializer<false, T> |
99 { | 113 { |
100 static void initialize(T* begin, T* end) | 114 static void initialize(T* begin, T* end) |
101 { | 115 { |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 | 338 |
325 T* buffer() { return m_buffer; } | 339 T* buffer() { return m_buffer; } |
326 const T* buffer() const { return m_buffer; } | 340 const T* buffer() const { return m_buffer; } |
327 size_t capacity() const { return m_capacity; } | 341 size_t capacity() const { return m_capacity; } |
328 | 342 |
329 void clearUnusedSlots(T* from, T* to) | 343 void clearUnusedSlots(T* from, T* to) |
330 { | 344 { |
331 VectorUnusedSlotClearer<Allocator::isGarbageCollected && (VectorTrai
ts<T>::needsDestruction || ShouldBeTraced<VectorTraits<T>>::value), T>::clear(fr
om, to); | 345 VectorUnusedSlotClearer<Allocator::isGarbageCollected && (VectorTrai
ts<T>::needsDestruction || ShouldBeTraced<VectorTraits<T>>::value), T>::clear(fr
om, to); |
332 } | 346 } |
333 | 347 |
| 348 void checkUnusedSlots(const T* from, const T* to) |
| 349 { |
| 350 #if ENABLE(ASSERT) && !defined(ANNOTATE_CONTIGUOUS_CONTAINER) |
| 351 VectorUnusedSlotClearer<Allocator::isGarbageCollected && (VectorTrai
ts<T>::needsDestruction || ShouldBeTraced<VectorTraits<T>>::value), T>::checkCle
ared(from, to); |
| 352 #endif |
| 353 } |
| 354 |
334 protected: | 355 protected: |
335 VectorBufferBase() | 356 VectorBufferBase() |
336 : m_buffer(0) | 357 : m_buffer(0) |
337 , m_capacity(0) | 358 , m_capacity(0) |
338 { | 359 { |
339 } | 360 } |
340 | 361 |
341 VectorBufferBase(T* buffer, size_t capacity) | 362 VectorBufferBase(T* buffer, size_t capacity) |
342 : m_buffer(buffer) | 363 : m_buffer(buffer) |
343 , m_capacity(capacity) | 364 , m_capacity(capacity) |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
412 std::swap(m_capacity, other.m_capacity); | 433 std::swap(m_capacity, other.m_capacity); |
413 } | 434 } |
414 | 435 |
415 using Base::allocateBuffer; | 436 using Base::allocateBuffer; |
416 using Base::allocationSize; | 437 using Base::allocationSize; |
417 | 438 |
418 using Base::buffer; | 439 using Base::buffer; |
419 using Base::capacity; | 440 using Base::capacity; |
420 | 441 |
421 using Base::clearUnusedSlots; | 442 using Base::clearUnusedSlots; |
| 443 using Base::checkUnusedSlots; |
422 | 444 |
423 bool hasOutOfLineBuffer() const | 445 bool hasOutOfLineBuffer() const |
424 { | 446 { |
425 // When inlineCapacity is 0 we have an out of line buffer if we have
a buffer. | 447 // When inlineCapacity is 0 we have an out of line buffer if we have
a buffer. |
426 return buffer(); | 448 return buffer(); |
427 } | 449 } |
428 | 450 |
429 protected: | 451 protected: |
430 using Base::m_size; | 452 using Base::m_size; |
431 | 453 |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
532 void swapVectorBuffer(VectorBuffer<T, inlineCapacity, Allocator>& other) | 554 void swapVectorBuffer(VectorBuffer<T, inlineCapacity, Allocator>& other) |
533 { | 555 { |
534 typedef VectorTypeOperations<T> TypeOperations; | 556 typedef VectorTypeOperations<T> TypeOperations; |
535 | 557 |
536 if (buffer() == inlineBuffer() && other.buffer() == other.inlineBuff
er()) { | 558 if (buffer() == inlineBuffer() && other.buffer() == other.inlineBuff
er()) { |
537 ASSERT(m_capacity == other.m_capacity); | 559 ASSERT(m_capacity == other.m_capacity); |
538 if (m_size > other.m_size) { | 560 if (m_size > other.m_size) { |
539 ANNOTATE_CHANGE_SIZE(other.inlineBuffer(), inlineCapacity, o
ther.m_size, m_size); | 561 ANNOTATE_CHANGE_SIZE(other.inlineBuffer(), inlineCapacity, o
ther.m_size, m_size); |
540 TypeOperations::swap(inlineBuffer(), inlineBuffer() + other.
m_size, other.inlineBuffer()); | 562 TypeOperations::swap(inlineBuffer(), inlineBuffer() + other.
m_size, other.inlineBuffer()); |
541 TypeOperations::move(inlineBuffer() + other.m_size, inlineBu
ffer() + m_size, other.inlineBuffer() + other.m_size); | 563 TypeOperations::move(inlineBuffer() + other.m_size, inlineBu
ffer() + m_size, other.inlineBuffer() + other.m_size); |
| 564 Base::clearUnusedSlots(inlineBuffer() + other.m_size, inline
Buffer() + m_size); |
542 ANNOTATE_CHANGE_SIZE(inlineBuffer(), inlineCapacity, m_size,
other.m_size); | 565 ANNOTATE_CHANGE_SIZE(inlineBuffer(), inlineCapacity, m_size,
other.m_size); |
543 } else { | 566 } else { |
544 ANNOTATE_CHANGE_SIZE(inlineBuffer(), inlineCapacity, m_size,
other.m_size); | 567 ANNOTATE_CHANGE_SIZE(inlineBuffer(), inlineCapacity, m_size,
other.m_size); |
545 TypeOperations::swap(inlineBuffer(), inlineBuffer() + m_size
, other.inlineBuffer()); | 568 TypeOperations::swap(inlineBuffer(), inlineBuffer() + m_size
, other.inlineBuffer()); |
546 TypeOperations::move(other.inlineBuffer() + m_size, other.in
lineBuffer() + other.m_size, inlineBuffer() + m_size); | 569 TypeOperations::move(other.inlineBuffer() + m_size, other.in
lineBuffer() + other.m_size, inlineBuffer() + m_size); |
| 570 Base::clearUnusedSlots(other.inlineBuffer() + m_size, other.
inlineBuffer() + other.m_size); |
547 ANNOTATE_CHANGE_SIZE(other.inlineBuffer(), inlineCapacity, o
ther.m_size, m_size); | 571 ANNOTATE_CHANGE_SIZE(other.inlineBuffer(), inlineCapacity, o
ther.m_size, m_size); |
548 } | 572 } |
549 } else if (buffer() == inlineBuffer()) { | 573 } else if (buffer() == inlineBuffer()) { |
550 ANNOTATE_DELETE_BUFFER(m_buffer, inlineCapacity, m_size); | 574 ANNOTATE_DELETE_BUFFER(m_buffer, inlineCapacity, m_size); |
551 m_buffer = other.m_buffer; | 575 m_buffer = other.m_buffer; |
552 other.m_buffer = other.inlineBuffer(); | 576 other.m_buffer = other.inlineBuffer(); |
553 ANNOTATE_NEW_BUFFER(other.m_buffer, inlineCapacity, m_size); | 577 ANNOTATE_NEW_BUFFER(other.m_buffer, inlineCapacity, m_size); |
554 TypeOperations::move(inlineBuffer(), inlineBuffer() + m_size, ot
her.inlineBuffer()); | 578 TypeOperations::move(inlineBuffer(), inlineBuffer() + m_size, ot
her.inlineBuffer()); |
| 579 Base::clearUnusedSlots(inlineBuffer(), inlineBuffer() + m_size); |
555 std::swap(m_capacity, other.m_capacity); | 580 std::swap(m_capacity, other.m_capacity); |
556 } else if (other.buffer() == other.inlineBuffer()) { | 581 } else if (other.buffer() == other.inlineBuffer()) { |
557 ANNOTATE_DELETE_BUFFER(other.m_buffer, inlineCapacity, other.m_s
ize); | 582 ANNOTATE_DELETE_BUFFER(other.m_buffer, inlineCapacity, other.m_s
ize); |
558 other.m_buffer = m_buffer; | 583 other.m_buffer = m_buffer; |
559 m_buffer = inlineBuffer(); | 584 m_buffer = inlineBuffer(); |
560 ANNOTATE_NEW_BUFFER(m_buffer, inlineCapacity, other.m_size); | 585 ANNOTATE_NEW_BUFFER(m_buffer, inlineCapacity, other.m_size); |
561 TypeOperations::move(other.inlineBuffer(), other.inlineBuffer()
+ other.m_size, inlineBuffer()); | 586 TypeOperations::move(other.inlineBuffer(), other.inlineBuffer()
+ other.m_size, inlineBuffer()); |
| 587 Base::clearUnusedSlots(other.inlineBuffer(), other.inlineBuffer(
) + other.m_size); |
562 std::swap(m_capacity, other.m_capacity); | 588 std::swap(m_capacity, other.m_capacity); |
563 } else { | 589 } else { |
564 std::swap(m_buffer, other.m_buffer); | 590 std::swap(m_buffer, other.m_buffer); |
565 std::swap(m_capacity, other.m_capacity); | 591 std::swap(m_capacity, other.m_capacity); |
566 } | 592 } |
567 } | 593 } |
568 | 594 |
569 using Base::buffer; | 595 using Base::buffer; |
570 using Base::capacity; | 596 using Base::capacity; |
571 | 597 |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
772 void shrinkCapacity(size_t newCapacity); | 798 void shrinkCapacity(size_t newCapacity); |
773 template<typename U> void appendSlowCase(const U&); | 799 template<typename U> void appendSlowCase(const U&); |
774 | 800 |
775 using Base::m_size; | 801 using Base::m_size; |
776 using Base::buffer; | 802 using Base::buffer; |
777 using Base::capacity; | 803 using Base::capacity; |
778 using Base::swapVectorBuffer; | 804 using Base::swapVectorBuffer; |
779 using Base::allocateBuffer; | 805 using Base::allocateBuffer; |
780 using Base::allocationSize; | 806 using Base::allocationSize; |
781 using Base::clearUnusedSlots; | 807 using Base::clearUnusedSlots; |
| 808 using Base::checkUnusedSlots; |
782 }; | 809 }; |
783 | 810 |
784 template<typename T, size_t inlineCapacity, typename Allocator> | 811 template<typename T, size_t inlineCapacity, typename Allocator> |
785 Vector<T, inlineCapacity, Allocator>::Vector(const Vector& other) | 812 Vector<T, inlineCapacity, Allocator>::Vector(const Vector& other) |
786 : Base(other.capacity()) | 813 : Base(other.capacity()) |
787 { | 814 { |
788 ANNOTATE_NEW_BUFFER(begin(), capacity(), other.size()); | 815 ANNOTATE_NEW_BUFFER(begin(), capacity(), other.size()); |
789 m_size = other.size(); | 816 m_size = other.size(); |
790 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); | 817 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); |
791 } | 818 } |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
963 { | 990 { |
964 expandCapacity(newMinCapacity); | 991 expandCapacity(newMinCapacity); |
965 return ptr; | 992 return ptr; |
966 } | 993 } |
967 | 994 |
968 template<typename T, size_t inlineCapacity, typename Allocator> | 995 template<typename T, size_t inlineCapacity, typename Allocator> |
969 inline void Vector<T, inlineCapacity, Allocator>::resize(size_t size) | 996 inline void Vector<T, inlineCapacity, Allocator>::resize(size_t size) |
970 { | 997 { |
971 if (size <= m_size) { | 998 if (size <= m_size) { |
972 TypeOperations::destruct(begin() + size, end()); | 999 TypeOperations::destruct(begin() + size, end()); |
| 1000 clearUnusedSlots(begin() + size, end()); |
973 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size); | 1001 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size); |
974 } else { | 1002 } else { |
975 if (size > capacity()) | 1003 if (size > capacity()) |
976 expandCapacity(size); | 1004 expandCapacity(size); |
977 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size); | 1005 ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size); |
978 TypeOperations::initialize(end(), begin() + size); | 1006 TypeOperations::initialize(end(), begin() + size); |
979 } | 1007 } |
980 | 1008 |
981 m_size = size; | 1009 m_size = size; |
982 } | 1010 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1019 // The check is just a static hint for a compiler to indicate that | 1047 // The check is just a static hint for a compiler to indicate that |
1020 // Base::expandBuffer returns false if Allocator is a DefaultAllocator. | 1048 // Base::expandBuffer returns false if Allocator is a DefaultAllocator. |
1021 if (Allocator::isGarbageCollected && Base::expandBuffer(newCapacity)) { | 1049 if (Allocator::isGarbageCollected && Base::expandBuffer(newCapacity)) { |
1022 ANNOTATE_CHANGE_CAPACITY(begin(), oldCapacity, m_size, capacity()); | 1050 ANNOTATE_CHANGE_CAPACITY(begin(), oldCapacity, m_size, capacity()); |
1023 return; | 1051 return; |
1024 } | 1052 } |
1025 T* oldEnd = end(); | 1053 T* oldEnd = end(); |
1026 Base::allocateExpandedBuffer(newCapacity); | 1054 Base::allocateExpandedBuffer(newCapacity); |
1027 ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size); | 1055 ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size); |
1028 TypeOperations::move(oldBuffer, oldEnd, begin()); | 1056 TypeOperations::move(oldBuffer, oldEnd, begin()); |
| 1057 clearUnusedSlots(oldBuffer, oldEnd); |
1029 ANNOTATE_DELETE_BUFFER(oldBuffer, oldCapacity, m_size); | 1058 ANNOTATE_DELETE_BUFFER(oldBuffer, oldCapacity, m_size); |
1030 Base::deallocateBuffer(oldBuffer); | 1059 Base::deallocateBuffer(oldBuffer); |
1031 } | 1060 } |
1032 | 1061 |
1033 template<typename T, size_t inlineCapacity, typename Allocator> | 1062 template<typename T, size_t inlineCapacity, typename Allocator> |
1034 inline void Vector<T, inlineCapacity, Allocator>::reserveInitialCapacity(siz
e_t initialCapacity) | 1063 inline void Vector<T, inlineCapacity, Allocator>::reserveInitialCapacity(siz
e_t initialCapacity) |
1035 { | 1064 { |
1036 ASSERT(!m_size); | 1065 ASSERT(!m_size); |
1037 ASSERT(capacity() == INLINE_CAPACITY); | 1066 ASSERT(capacity() == INLINE_CAPACITY); |
1038 if (initialCapacity > INLINE_CAPACITY) { | 1067 if (initialCapacity > INLINE_CAPACITY) { |
(...skipping 20 matching lines...) Expand all Loading... |
1059 if (Base::shrinkBuffer(newCapacity)) { | 1088 if (Base::shrinkBuffer(newCapacity)) { |
1060 ANNOTATE_CHANGE_CAPACITY(begin(), oldCapacity, m_size, capacity(
)); | 1089 ANNOTATE_CHANGE_CAPACITY(begin(), oldCapacity, m_size, capacity(
)); |
1061 return; | 1090 return; |
1062 } | 1091 } |
1063 | 1092 |
1064 T* oldEnd = end(); | 1093 T* oldEnd = end(); |
1065 Base::allocateBuffer(newCapacity); | 1094 Base::allocateBuffer(newCapacity); |
1066 if (begin() != oldBuffer) { | 1095 if (begin() != oldBuffer) { |
1067 ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size); | 1096 ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size); |
1068 TypeOperations::move(oldBuffer, oldEnd, begin()); | 1097 TypeOperations::move(oldBuffer, oldEnd, begin()); |
| 1098 clearUnusedSlots(oldBuffer, oldEnd); |
1069 ANNOTATE_DELETE_BUFFER(oldBuffer, oldCapacity, m_size); | 1099 ANNOTATE_DELETE_BUFFER(oldBuffer, oldCapacity, m_size); |
1070 } | 1100 } |
1071 } else { | 1101 } else { |
1072 Base::resetBufferPointer(); | 1102 Base::resetBufferPointer(); |
1073 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER | 1103 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER |
1074 if (oldBuffer != begin()) { | 1104 if (oldBuffer != begin()) { |
1075 ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size); | 1105 ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size); |
1076 ANNOTATE_DELETE_BUFFER(oldBuffer, oldCapacity, m_size); | 1106 ANNOTATE_DELETE_BUFFER(oldBuffer, oldCapacity, m_size); |
1077 } | 1107 } |
1078 #endif | 1108 #endif |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1280 template<typename T, size_t inlineCapacity, typename Allocator> | 1310 template<typename T, size_t inlineCapacity, typename Allocator> |
1281 template<typename VisitorDispatcher> | 1311 template<typename VisitorDispatcher> |
1282 void Vector<T, inlineCapacity, Allocator>::trace(VisitorDispatcher visitor) | 1312 void Vector<T, inlineCapacity, Allocator>::trace(VisitorDispatcher visitor) |
1283 { | 1313 { |
1284 ASSERT(Allocator::isGarbageCollected); // Garbage collector must be enab
led. | 1314 ASSERT(Allocator::isGarbageCollected); // Garbage collector must be enab
led. |
1285 const T* bufferBegin = buffer(); | 1315 const T* bufferBegin = buffer(); |
1286 const T* bufferEnd = buffer() + size(); | 1316 const T* bufferEnd = buffer() + size(); |
1287 if (ShouldBeTraced<VectorTraits<T>>::value) { | 1317 if (ShouldBeTraced<VectorTraits<T>>::value) { |
1288 for (const T* bufferEntry = bufferBegin; bufferEntry != bufferEnd; b
ufferEntry++) | 1318 for (const T* bufferEntry = bufferBegin; bufferEntry != bufferEnd; b
ufferEntry++) |
1289 Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>
(visitor, *const_cast<T*>(bufferEntry)); | 1319 Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>
(visitor, *const_cast<T*>(bufferEntry)); |
| 1320 checkUnusedSlots(buffer() + size(), buffer() + capacity()); |
1290 } | 1321 } |
1291 if (this->hasOutOfLineBuffer()) | 1322 if (this->hasOutOfLineBuffer()) |
1292 Allocator::markNoTracing(visitor, buffer()); | 1323 Allocator::markNoTracing(visitor, buffer()); |
1293 } | 1324 } |
1294 | 1325 |
1295 #if !ENABLE(OILPAN) | 1326 #if !ENABLE(OILPAN) |
1296 template<typename T, size_t N> | 1327 template<typename T, size_t N> |
1297 struct NeedsTracing<Vector<T, N>> { | 1328 struct NeedsTracing<Vector<T, N>> { |
1298 static const bool value = false; | 1329 static const bool value = false; |
1299 }; | 1330 }; |
1300 #endif | 1331 #endif |
1301 | 1332 |
1302 } // namespace WTF | 1333 } // namespace WTF |
1303 | 1334 |
1304 using WTF::Vector; | 1335 using WTF::Vector; |
1305 | 1336 |
1306 #endif // WTF_Vector_h | 1337 #endif // WTF_Vector_h |
OLD | NEW |