diff options
Diffstat (limited to 'Source/JavaScriptCore/heap/GCSegmentedArray.h')
-rw-r--r-- | Source/JavaScriptCore/heap/GCSegmentedArray.h | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/heap/GCSegmentedArray.h b/Source/JavaScriptCore/heap/GCSegmentedArray.h new file mode 100644 index 000000000..8aeba1025 --- /dev/null +++ b/Source/JavaScriptCore/heap/GCSegmentedArray.h @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2014 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GCSegmentedArray_h +#define GCSegmentedArray_h + +#include <wtf/DoublyLinkedList.h> +#include <wtf/Vector.h> + +namespace JSC { + +template <typename T> +class GCArraySegment : public DoublyLinkedListNode<GCArraySegment<T>> { + friend class WTF::DoublyLinkedListNode<GCArraySegment<T>>; +public: + GCArraySegment() + : DoublyLinkedListNode<GCArraySegment<T>>() +#if !ASSERT_DISABLED + , m_top(0) +#endif + { + } + + static GCArraySegment* create(); + static void destroy(GCArraySegment*); + + T* data() + { + return bitwise_cast<T*>(this + 1); + } + + static const size_t blockSize = 4 * KB; + + GCArraySegment* m_prev; + GCArraySegment* m_next; +#if !ASSERT_DISABLED + size_t m_top; +#endif +}; + +template <typename T> class GCSegmentedArrayIterator; + +template <typename T> +class GCSegmentedArray { + friend class GCSegmentedArrayIterator<T>; + friend class GCSegmentedArrayIterator<const T>; +public: + GCSegmentedArray(); + ~GCSegmentedArray(); + + void append(T); + + bool canRemoveLast(); + const T removeLast(); + bool refill(); + + size_t size(); + bool isEmpty(); + + void fillVector(Vector<T>&); + void clear(); + + typedef GCSegmentedArrayIterator<T> iterator; + iterator begin() const { return GCSegmentedArrayIterator<T>(m_segments.head(), m_top); } + iterator end() const { return GCSegmentedArrayIterator<T>(); } + +protected: + template <size_t size> struct CapacityFromSize { + static const size_t value = (size - sizeof(GCArraySegment<T>)) / sizeof(T); + }; + + void expand(); + + size_t postIncTop(); + size_t preDecTop(); + void setTopForFullSegment(); + void setTopForEmptySegment(); + size_t top(); + + void validatePrevious(); + + DoublyLinkedList<GCArraySegment<T>> m_segments; + + JS_EXPORT_PRIVATE static const size_t s_segmentCapacity = CapacityFromSize<GCArraySegment<T>::blockSize>::value; + size_t m_top; + size_t m_numberOfSegments; +}; + +template <typename T> +class GCSegmentedArrayIterator { + friend class GCSegmentedArray<T>; +public: + GCSegmentedArrayIterator() + : m_currentSegment(0) + , m_currentOffset(0) + { + } + + T& get() { return m_currentSegment->data()[m_currentOffset]; } + T& operator*() { return get(); } + T& operator->() { return get(); } + + bool operator==(const GCSegmentedArrayIterator& other) + { + return m_currentSegment == other.m_currentSegment && m_currentOffset == other.m_currentOffset; + } + + bool operator!=(const GCSegmentedArrayIterator& other) + { + return !(*this == other); + } + + GCSegmentedArrayIterator& operator++() + { + ASSERT(m_currentSegment); + + m_currentOffset++; + + if (m_currentOffset >= m_offsetLimit) { + m_currentSegment = m_currentSegment->next(); + m_currentOffset = 0; + m_offsetLimit = GCSegmentedArray<T>::s_segmentCapacity; + } + + return *this; + } + +private: + GCSegmentedArrayIterator(GCArraySegment<T>* start, size_t top) + : m_currentSegment(start) + , m_currentOffset(0) + , m_offsetLimit(top) + { + if (!m_offsetLimit) + m_currentSegment = nullptr; + } + + GCArraySegment<T>* m_currentSegment; + size_t m_currentOffset; + size_t m_offsetLimit; +}; + +} // namespace JSC + +#endif // GCSegmentedArray_h |