Index: Source/wtf/Deque.h |
diff --git a/Source/wtf/Deque.h b/Source/wtf/Deque.h |
index d46f8fcd580fd8ea0cc7fc10a0ff8527963c26e0..e9fb0ce8742101e03d4268543197001d37e88d12 100644 |
--- a/Source/wtf/Deque.h |
+++ b/Source/wtf/Deque.h |
@@ -39,27 +39,83 @@ |
namespace WTF { |
- template<typename T, size_t inlineCapacity> class DequeIteratorBase; |
- template<typename T, size_t inlineCapacity> class DequeIterator; |
- template<typename T, size_t inlineCapacity> class DequeConstIterator; |
+ template<typename T, size_t inlineCapacity, typename Allocator> class DequeIteratorBase; |
+ template<typename T, size_t inlineCapacity, typename Allocator> class DequeIterator; |
+ template<typename T, size_t inlineCapacity, typename Allocator> class DequeConstIterator; |
+ |
+ // All non-GC managed deques need a destructor. This destructor will |
+ // simply call finalize on the actual deque type. |
+ template<typename Derived, typename Elements, bool hasInlineCapacity, bool isGarbageCollected> |
+ class DequeDestructorBase { |
Mikhail
2014/04/08 11:03:01
This looks similar to the existing VectorDestructo
Erik Corry
2014/04/08 11:48:53
Good point, yes we can!
|
+ public: |
+ ~DequeDestructorBase() { static_cast<Derived*>(this)->finalize(); } |
+ }; |
- template<typename T, size_t inlineCapacity = 0> |
- class Deque { |
- WTF_MAKE_FAST_ALLOCATED; |
+ // Heap-allocated deques with no inlineCapacity never need a destructor. |
+ template<typename Derived, typename Elements> |
+ class DequeDestructorBase<Derived, Elements, false, true> { }; |
+ |
+ // Heap-allocator deques with inlineCapacity need a destructor if the |
+ // inline elements do. The use of VectorTraits<Elements>::needsDestruction |
+ // is delayed until we know that inlineCapacity is non-zero to allow |
+ // classes that recursively refer to themselves in deque members. If |
+ // inlineCapacity is non-zero doing so would have undefined meaning, so in |
+ // this case we can use HeapDequeWithInlineCapacityDestructorBase to |
+ // define a destructor depending on the value of |
+ // VectorTraits<Elements>::needsDestruction. |
+ template<typename Derived, bool elementsNeedsDestruction> |
+ class HeapDequeWithInlineCapacityDestructorBase; |
+ |
+ template<typename Derived> |
+ class HeapDequeWithInlineCapacityDestructorBase<Derived, true> { |
public: |
- typedef DequeIterator<T, inlineCapacity> iterator; |
- typedef DequeConstIterator<T, inlineCapacity> const_iterator; |
+ ~HeapDequeWithInlineCapacityDestructorBase() { static_cast<Derived*>(this)->finalize(); } |
+ }; |
+ |
+ template<typename Derived> |
+ class HeapDequeWithInlineCapacityDestructorBase<Derived, false> { }; |
+ |
+ template<typename Derived, typename Elements> |
+ class DequeDestructorBase<Derived, Elements, true, true> : public HeapDequeWithInlineCapacityDestructorBase<Derived, VectorTraits<Elements>::needsDestruction> { }; |
+ |
+ template<typename T, size_t inlineCapacity = 0, typename Allocator = DefaultAllocator> |
+ class Deque : public DequeDestructorBase<Deque<T, inlineCapacity, Allocator>, T, (inlineCapacity > 0), Allocator::isGarbageCollected> { |
+ public: |
+ typedef DequeIterator<T, inlineCapacity, Allocator> iterator; |
+ typedef DequeConstIterator<T, inlineCapacity, Allocator> const_iterator; |
typedef std::reverse_iterator<iterator> reverse_iterator; |
typedef std::reverse_iterator<const_iterator> const_reverse_iterator; |
typedef PassTraits<T> Pass; |
typedef typename PassTraits<T>::PassType PassType; |
+ void* operator new(size_t size) |
+ { |
+ return Allocator::template malloc<void*, Deque>(size); |
+ } |
+ void operator delete(void* p) { Allocator::free(p); } |
+ void* operator new[](size_t size) { return Allocator::template newArray<Vector>(size); } |
+ void operator delete[](void* p) { Allocator::deleteArray(p); } |
+ void* operator new(size_t, NotNullTag, void* location) |
+ { |
+ ASSERT(location); |
+ return location; |
+ } |
+ |
Deque(); |
- Deque(const Deque<T, inlineCapacity>&); |
- Deque& operator=(const Deque<T, inlineCapacity>&); |
- ~Deque(); |
+ Deque(const Deque<T, inlineCapacity, Allocator>&); |
+ // FIXME: Doesn't work if there is an inline buffer, so for now we only |
+ // define the version without. The issue is that the VectorBuffer with |
+ // inline capacity uses the m_size field to know how much of the array to |
+ // copy, but that field is unused and unitialized with deques, because they |
+ // do not fill the buffer only from 0 to m_size. |
+ Deque<T, 0, Allocator>& operator=(const Deque&); |
+ |
+ void finalize(); |
+ void finalizeGarbageCollectedObject() { finalize(); } |
- void swap(Deque<T, inlineCapacity>&); |
+ // We hard wire the inlineCapacity to zero here. See the comment on the |
+ // assignment operator above. |
Mikhail
2014/04/08 11:03:01
did not get how we wire the inlineCapacity to zero
Erik Corry
2014/04/08 11:48:53
It seems I didn't wire the inlineCapacity to zero
|
+ void swap(Deque&); |
size_t size() const { return m_start <= m_end ? m_end - m_start : m_end + m_buffer.capacity() - m_start; } |
bool isEmpty() const { return m_start == m_end; } |
@@ -93,12 +149,14 @@ namespace WTF { |
template<typename Predicate> |
iterator findIf(Predicate&); |
+ void trace(typename Allocator::Visitor*); |
+ |
private: |
- friend class DequeIteratorBase<T, inlineCapacity>; |
+ friend class DequeIteratorBase<T, inlineCapacity, Allocator>; |
- typedef VectorBuffer<T, inlineCapacity> Buffer; |
+ typedef VectorBuffer<T, inlineCapacity, Allocator> Buffer; |
typedef VectorTypeOperations<T> TypeOperations; |
- typedef DequeIteratorBase<T, inlineCapacity> IteratorBase; |
+ typedef DequeIteratorBase<T, inlineCapacity, Allocator> IteratorBase; |
void remove(size_t position); |
void destroyAll(); |
@@ -110,13 +168,13 @@ namespace WTF { |
unsigned m_end; |
}; |
- template<typename T, size_t inlineCapacity = 0> |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
class DequeIteratorBase { |
protected: |
DequeIteratorBase(); |
- DequeIteratorBase(const Deque<T, inlineCapacity>*, size_t); |
+ DequeIteratorBase(const Deque<T, inlineCapacity, Allocator>*, size_t); |
DequeIteratorBase(const DequeIteratorBase&); |
- DequeIteratorBase& operator=(const DequeIteratorBase&); |
+ DequeIteratorBase<T, 0, Allocator>& operator=(const DequeIteratorBase<T, 0, Allocator>&); |
~DequeIteratorBase(); |
void assign(const DequeIteratorBase& other) { *this = other; } |
@@ -130,17 +188,17 @@ namespace WTF { |
bool isEqual(const DequeIteratorBase&) const; |
private: |
- Deque<T, inlineCapacity>* m_deque; |
+ Deque<T, inlineCapacity, Allocator>* m_deque; |
unsigned m_index; |
- friend class Deque<T, inlineCapacity>; |
+ friend class Deque<T, inlineCapacity, Allocator>; |
}; |
- template<typename T, size_t inlineCapacity = 0> |
- class DequeIterator : public DequeIteratorBase<T, inlineCapacity> { |
+ template<typename T, size_t inlineCapacity = 0, typename Allocator = DefaultAllocator> |
+ class DequeIterator : public DequeIteratorBase<T, inlineCapacity, Allocator> { |
private: |
- typedef DequeIteratorBase<T, inlineCapacity> Base; |
- typedef DequeIterator<T, inlineCapacity> Iterator; |
+ typedef DequeIteratorBase<T, inlineCapacity, Allocator> Base; |
+ typedef DequeIterator<T, inlineCapacity, Allocator> Iterator; |
public: |
typedef ptrdiff_t difference_type; |
@@ -149,7 +207,7 @@ namespace WTF { |
typedef T& reference; |
typedef std::bidirectional_iterator_tag iterator_category; |
- DequeIterator(Deque<T, inlineCapacity>* deque, size_t index) : Base(deque, index) { } |
+ DequeIterator(Deque<T, inlineCapacity, Allocator>* deque, size_t index) : Base(deque, index) { } |
DequeIterator(const Iterator& other) : Base(other) { } |
DequeIterator& operator=(const Iterator& other) { Base::assign(other); return *this; } |
@@ -166,12 +224,12 @@ namespace WTF { |
// postfix -- intentionally omitted |
}; |
- template<typename T, size_t inlineCapacity = 0> |
- class DequeConstIterator : public DequeIteratorBase<T, inlineCapacity> { |
+ template<typename T, size_t inlineCapacity = 0, typename Allocator = DefaultAllocator> |
+ class DequeConstIterator : public DequeIteratorBase<T, inlineCapacity, Allocator> { |
private: |
- typedef DequeIteratorBase<T, inlineCapacity> Base; |
- typedef DequeConstIterator<T, inlineCapacity> Iterator; |
- typedef DequeIterator<T, inlineCapacity> NonConstIterator; |
+ typedef DequeIteratorBase<T, inlineCapacity, Allocator> Base; |
+ typedef DequeConstIterator<T, inlineCapacity, Allocator> Iterator; |
+ typedef DequeIterator<T, inlineCapacity, Allocator> NonConstIterator; |
public: |
typedef ptrdiff_t difference_type; |
@@ -180,7 +238,7 @@ namespace WTF { |
typedef const T& reference; |
typedef std::bidirectional_iterator_tag iterator_category; |
- DequeConstIterator(const Deque<T, inlineCapacity>* deque, size_t index) : Base(deque, index) { } |
+ DequeConstIterator(const Deque<T, inlineCapacity, Allocator>* deque, size_t index) : Base(deque, index) { } |
DequeConstIterator(const Iterator& other) : Base(other) { } |
DequeConstIterator(const NonConstIterator& other) : Base(other) { } |
@@ -199,15 +257,15 @@ namespace WTF { |
// postfix -- intentionally omitted |
}; |
- template<typename T, size_t inlineCapacity> |
- inline Deque<T, inlineCapacity>::Deque() |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline Deque<T, inlineCapacity, Allocator>::Deque() |
: m_start(0) |
, m_end(0) |
{ |
} |
- template<typename T, size_t inlineCapacity> |
- inline Deque<T, inlineCapacity>::Deque(const Deque<T, inlineCapacity>& other) |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline Deque<T, inlineCapacity, Allocator>::Deque(const Deque<T, inlineCapacity, Allocator>& other) |
: m_buffer(other.m_buffer.capacity()) |
, m_start(other.m_start) |
, m_end(other.m_end) |
@@ -221,27 +279,25 @@ namespace WTF { |
} |
} |
- template<typename T, size_t inlineCapacity> |
- void deleteAllValues(const Deque<T, inlineCapacity>& collection) |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ void deleteAllValues(const Deque<T, inlineCapacity, Allocator>& collection) |
{ |
- typedef typename Deque<T, inlineCapacity>::const_iterator iterator; |
+ typedef typename Deque<T, inlineCapacity, Allocator>::const_iterator iterator; |
iterator end = collection.end(); |
for (iterator it = collection.begin(); it != end; ++it) |
delete *it; |
} |
- template<typename T, size_t inlineCapacity> |
- inline Deque<T, inlineCapacity>& Deque<T, inlineCapacity>::operator=(const Deque<T, inlineCapacity>& other) |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline Deque<T, 0, Allocator>& Deque<T, inlineCapacity, Allocator>::operator=(const Deque& other) |
{ |
- // FIXME: This is inefficient if we're using an inline buffer and T is |
- // expensive to copy since it will copy the buffer twice instead of once. |
Deque<T> copy(other); |
swap(copy); |
return *this; |
} |
- template<typename T, size_t inlineCapacity> |
- inline void Deque<T, inlineCapacity>::destroyAll() |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline void Deque<T, inlineCapacity, Allocator>::destroyAll() |
{ |
if (m_start <= m_end) |
TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffer() + m_end); |
@@ -251,23 +307,36 @@ namespace WTF { |
} |
} |
- template<typename T, size_t inlineCapacity> |
- inline Deque<T, inlineCapacity>::~Deque() |
+ // Off-GC-heap deques: Destructor should be called. |
+ // On-GC-heap deques: Destructor should be called for inline buffers |
+ // (if any) but destructor shouldn't be called for vector backing since |
+ // it is managed by the traced GC heap. |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline void Deque<T, inlineCapacity, Allocator>::finalize() |
{ |
- destroyAll(); |
+ if (!inlineCapacity) { |
+ if (LIKELY(!m_buffer.buffer())) |
Mikhail
2014/04/08 11:03:01
so not having the buffer is most expected?
Erik Corry
2014/04/08 11:48:53
Removed the LIKELY, as I don't think it really add
|
+ return; |
+ } |
+ if (LIKELY(!isEmpty()) && !(Allocator::isGarbageCollected && m_buffer.hasOutOfLineBuffer())) { |
+ destroyAll(); |
+ } |
+ |
m_buffer.destruct(); |
} |
- template<typename T, size_t inlineCapacity> |
- inline void Deque<T, inlineCapacity>::swap(Deque<T, inlineCapacity>& other) |
+ // FIXME: Doesn't work if there is an inline buffer, so for now we only |
+ // define the version without. |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline void Deque<T, inlineCapacity, Allocator>::swap(Deque& other) |
{ |
std::swap(m_start, other.m_start); |
std::swap(m_end, other.m_end); |
m_buffer.swapVectorBuffer(other.m_buffer); |
} |
- template<typename T, size_t inlineCapacity> |
- inline void Deque<T, inlineCapacity>::clear() |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline void Deque<T, inlineCapacity, Allocator>::clear() |
{ |
destroyAll(); |
m_start = 0; |
@@ -276,9 +345,9 @@ namespace WTF { |
m_buffer.resetBufferPointer(); |
} |
- template<typename T, size_t inlineCapacity> |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
template<typename Predicate> |
- inline DequeIterator<T, inlineCapacity> Deque<T, inlineCapacity>::findIf(Predicate& predicate) |
+ inline DequeIterator<T, inlineCapacity, Allocator> Deque<T, inlineCapacity, Allocator>::findIf(Predicate& predicate) |
{ |
iterator end_iterator = end(); |
for (iterator it = begin(); it != end_iterator; ++it) { |
@@ -288,8 +357,8 @@ namespace WTF { |
return end_iterator; |
} |
- template<typename T, size_t inlineCapacity> |
- inline void Deque<T, inlineCapacity>::expandCapacityIfNeeded() |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline void Deque<T, inlineCapacity, Allocator>::expandCapacityIfNeeded() |
{ |
if (m_start) { |
if (m_end + 1 != m_start) |
@@ -303,8 +372,8 @@ namespace WTF { |
expandCapacity(); |
} |
- template<typename T, size_t inlineCapacity> |
- void Deque<T, inlineCapacity>::expandCapacity() |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ void Deque<T, inlineCapacity, Allocator>::expandCapacity() |
{ |
size_t oldCapacity = m_buffer.capacity(); |
T* oldBuffer = m_buffer.buffer(); |
@@ -320,24 +389,24 @@ namespace WTF { |
m_buffer.deallocateBuffer(oldBuffer); |
} |
- template<typename T, size_t inlineCapacity> |
- inline typename Deque<T, inlineCapacity>::PassType Deque<T, inlineCapacity>::takeFirst() |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline typename Deque<T, inlineCapacity, Allocator>::PassType Deque<T, inlineCapacity, Allocator>::takeFirst() |
{ |
T oldFirst = Pass::transfer(first()); |
removeFirst(); |
return Pass::transfer(oldFirst); |
} |
- template<typename T, size_t inlineCapacity> |
- inline typename Deque<T, inlineCapacity>::PassType Deque<T, inlineCapacity>::takeLast() |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline typename Deque<T, inlineCapacity, Allocator>::PassType Deque<T, inlineCapacity, Allocator>::takeLast() |
{ |
T oldLast = Pass::transfer(last()); |
removeLast(); |
return Pass::transfer(oldLast); |
} |
- template<typename T, size_t inlineCapacity> template<typename U> |
- inline void Deque<T, inlineCapacity>::append(const U& value) |
+ template<typename T, size_t inlineCapacity, typename Allocator> template<typename U> |
+ inline void Deque<T, inlineCapacity, Allocator>::append(const U& value) |
{ |
expandCapacityIfNeeded(); |
new (NotNull, &m_buffer.buffer()[m_end]) T(value); |
@@ -347,8 +416,8 @@ namespace WTF { |
++m_end; |
} |
- template<typename T, size_t inlineCapacity> template<typename U> |
- inline void Deque<T, inlineCapacity>::prepend(const U& value) |
+ template<typename T, size_t inlineCapacity, typename Allocator> template<typename U> |
+ inline void Deque<T, inlineCapacity, Allocator>::prepend(const U& value) |
{ |
expandCapacityIfNeeded(); |
if (!m_start) |
@@ -358,8 +427,8 @@ namespace WTF { |
new (NotNull, &m_buffer.buffer()[m_start]) T(value); |
} |
- template<typename T, size_t inlineCapacity> |
- inline void Deque<T, inlineCapacity>::removeFirst() |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline void Deque<T, inlineCapacity, Allocator>::removeFirst() |
{ |
ASSERT(!isEmpty()); |
TypeOperations::destruct(&m_buffer.buffer()[m_start], &m_buffer.buffer()[m_start + 1]); |
@@ -369,8 +438,8 @@ namespace WTF { |
++m_start; |
} |
- template<typename T, size_t inlineCapacity> |
- inline void Deque<T, inlineCapacity>::removeLast() |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline void Deque<T, inlineCapacity, Allocator>::removeLast() |
{ |
ASSERT(!isEmpty()); |
if (!m_end) |
@@ -380,20 +449,20 @@ namespace WTF { |
TypeOperations::destruct(&m_buffer.buffer()[m_end], &m_buffer.buffer()[m_end + 1]); |
} |
- template<typename T, size_t inlineCapacity> |
- inline void Deque<T, inlineCapacity>::remove(iterator& it) |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline void Deque<T, inlineCapacity, Allocator>::remove(iterator& it) |
{ |
remove(it.m_index); |
} |
- template<typename T, size_t inlineCapacity> |
- inline void Deque<T, inlineCapacity>::remove(const_iterator& it) |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline void Deque<T, inlineCapacity, Allocator>::remove(const_iterator& it) |
{ |
remove(it.m_index); |
} |
- template<typename T, size_t inlineCapacity> |
- inline void Deque<T, inlineCapacity>::remove(size_t position) |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline void Deque<T, inlineCapacity, Allocator>::remove(size_t position) |
{ |
if (position == m_end) |
return; |
@@ -411,47 +480,47 @@ namespace WTF { |
} |
} |
- template<typename T, size_t inlineCapacity> |
- inline DequeIteratorBase<T, inlineCapacity>::DequeIteratorBase() |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline DequeIteratorBase<T, inlineCapacity, Allocator>::DequeIteratorBase() |
: m_deque(0) |
{ |
} |
- template<typename T, size_t inlineCapacity> |
- inline DequeIteratorBase<T, inlineCapacity>::DequeIteratorBase(const Deque<T, inlineCapacity>* deque, size_t index) |
- : m_deque(const_cast<Deque<T, inlineCapacity>*>(deque)) |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline DequeIteratorBase<T, inlineCapacity, Allocator>::DequeIteratorBase(const Deque<T, inlineCapacity, Allocator>* deque, size_t index) |
+ : m_deque(const_cast<Deque<T, inlineCapacity, Allocator>*>(deque)) |
, m_index(index) |
{ |
} |
- template<typename T, size_t inlineCapacity> |
- inline DequeIteratorBase<T, inlineCapacity>::DequeIteratorBase(const DequeIteratorBase& other) |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline DequeIteratorBase<T, inlineCapacity, Allocator>::DequeIteratorBase(const DequeIteratorBase& other) |
: m_deque(other.m_deque) |
, m_index(other.m_index) |
{ |
} |
- template<typename T, size_t inlineCapacity> |
- inline DequeIteratorBase<T, inlineCapacity>& DequeIteratorBase<T, inlineCapacity>::operator=(const DequeIteratorBase& other) |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline DequeIteratorBase<T, 0, Allocator>& DequeIteratorBase<T, inlineCapacity, Allocator>::operator=(const DequeIteratorBase<T, 0, Allocator>& other) |
{ |
m_deque = other.m_deque; |
m_index = other.m_index; |
return *this; |
} |
- template<typename T, size_t inlineCapacity> |
- inline DequeIteratorBase<T, inlineCapacity>::~DequeIteratorBase() |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline DequeIteratorBase<T, inlineCapacity, Allocator>::~DequeIteratorBase() |
{ |
} |
- template<typename T, size_t inlineCapacity> |
- inline bool DequeIteratorBase<T, inlineCapacity>::isEqual(const DequeIteratorBase& other) const |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline bool DequeIteratorBase<T, inlineCapacity, Allocator>::isEqual(const DequeIteratorBase& other) const |
{ |
return m_index == other.m_index; |
} |
- template<typename T, size_t inlineCapacity> |
- inline void DequeIteratorBase<T, inlineCapacity>::increment() |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline void DequeIteratorBase<T, inlineCapacity, Allocator>::increment() |
{ |
ASSERT(m_index != m_deque->m_end); |
ASSERT(m_deque->m_buffer.capacity()); |
@@ -461,8 +530,8 @@ namespace WTF { |
++m_index; |
} |
- template<typename T, size_t inlineCapacity> |
- inline void DequeIteratorBase<T, inlineCapacity>::decrement() |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline void DequeIteratorBase<T, inlineCapacity, Allocator>::decrement() |
{ |
ASSERT(m_index != m_deque->m_start); |
ASSERT(m_deque->m_buffer.capacity()); |
@@ -472,15 +541,15 @@ namespace WTF { |
--m_index; |
} |
- template<typename T, size_t inlineCapacity> |
- inline T* DequeIteratorBase<T, inlineCapacity>::after() const |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline T* DequeIteratorBase<T, inlineCapacity, Allocator>::after() const |
{ |
ASSERT(m_index != m_deque->m_end); |
return &m_deque->m_buffer.buffer()[m_index]; |
} |
- template<typename T, size_t inlineCapacity> |
- inline T* DequeIteratorBase<T, inlineCapacity>::before() const |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ inline T* DequeIteratorBase<T, inlineCapacity, Allocator>::before() const |
{ |
ASSERT(m_index != m_deque->m_start); |
if (!m_index) |
@@ -488,6 +557,30 @@ namespace WTF { |
return &m_deque->m_buffer.buffer()[m_index - 1]; |
} |
+ // This is only called if the allocator is a HeapAllocator. It is used when |
+ // visiting during a tracing GC. |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ void Deque<T, inlineCapacity, Allocator>::trace(typename Allocator::Visitor* visitor) |
+ { |
+ COMPILE_ASSERT(Allocator::isGarbageCollected, Garbage_collector_must_be_enabled); |
+ const T* bufferBegin = m_buffer.buffer(); |
+ const T* end = bufferBegin + m_end; |
+ if (ShouldBeTraced<VectorTraits<T> >::value) { |
+ if (m_start <= m_end) { |
+ for (const T* bufferEntry = bufferBegin + m_start; bufferEntry != end; bufferEntry++) |
Mikhail
2014/04/08 11:03:01
nit: ++bufferEntry
Erik Corry
2014/04/08 11:48:53
Style guide allows both.
|
+ Allocator::template trace<T, VectorTraits<T> >(visitor, *const_cast<T*>(bufferEntry)); |
+ } else { |
+ for (const T* bufferEntry = bufferBegin; bufferEntry != end; bufferEntry++) |
+ Allocator::template trace<T, VectorTraits<T> >(visitor, *const_cast<T*>(bufferEntry)); |
+ const T* bufferEnd = m_buffer.buffer() + m_buffer.capacity(); |
+ for (const T* bufferEntry = bufferBegin + m_start; bufferEntry != bufferEnd; bufferEntry++) |
+ Allocator::template trace<T, VectorTraits<T> >(visitor, *const_cast<T*>(bufferEntry)); |
+ } |
+ } |
+ if (m_buffer.hasOutOfLineBuffer()) |
+ Allocator::markNoTracing(visitor, m_buffer.buffer()); |
+ } |
+ |
} // namespace WTF |
using WTF::Deque; |