diff options
Diffstat (limited to 'Source/JavaScriptCore/heap/GCSegmentedArrayInlines.h')
-rw-r--r-- | Source/JavaScriptCore/heap/GCSegmentedArrayInlines.h | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/heap/GCSegmentedArrayInlines.h b/Source/JavaScriptCore/heap/GCSegmentedArrayInlines.h new file mode 100644 index 000000000..88e43cc9b --- /dev/null +++ b/Source/JavaScriptCore/heap/GCSegmentedArrayInlines.h @@ -0,0 +1,230 @@ +/* + * 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 GCSegmentedArrayInlines_h +#define GCSegmentedArrayInlines_h + +#include "GCSegmentedArray.h" + +namespace JSC { + +template <typename T> +GCSegmentedArray<T>::GCSegmentedArray() + : m_top(0) + , m_numberOfSegments(0) +{ + m_segments.push(GCArraySegment<T>::create()); + m_numberOfSegments++; +} + +template <typename T> +GCSegmentedArray<T>::~GCSegmentedArray() +{ + ASSERT(m_numberOfSegments == 1); + ASSERT(m_segments.size() == 1); + GCArraySegment<T>::destroy(m_segments.removeHead()); + m_numberOfSegments--; + ASSERT(!m_numberOfSegments); + ASSERT(!m_segments.size()); +} + +template <typename T> +void GCSegmentedArray<T>::clear() +{ + if (!m_segments.head()) + return; + GCArraySegment<T>* next; + for (GCArraySegment<T>* current = m_segments.head(); current->next(); current = next) { + next = current->next(); + m_segments.remove(current); + GCArraySegment<T>::destroy(current); + } + m_top = 0; + m_numberOfSegments = 1; +#if !ASSERT_DISABLED + m_segments.head()->m_top = 0; +#endif +} + +template <typename T> +void GCSegmentedArray<T>::expand() +{ + ASSERT(m_segments.head()->m_top == s_segmentCapacity); + + GCArraySegment<T>* nextSegment = GCArraySegment<T>::create(); + m_numberOfSegments++; + +#if !ASSERT_DISABLED + nextSegment->m_top = 0; +#endif + + m_segments.push(nextSegment); + setTopForEmptySegment(); + validatePrevious(); +} + +template <typename T> +bool GCSegmentedArray<T>::refill() +{ + validatePrevious(); + if (top()) + return true; + GCArraySegment<T>::destroy(m_segments.removeHead()); + ASSERT(m_numberOfSegments > 1); + m_numberOfSegments--; + setTopForFullSegment(); + validatePrevious(); + return true; +} + +template <typename T> +void GCSegmentedArray<T>::fillVector(Vector<T>& vector) +{ + ASSERT(vector.size() == size()); + + GCArraySegment<T>* currentSegment = m_segments.head(); + if (!currentSegment) + return; + + unsigned count = 0; + for (unsigned i = 0; i < m_top; ++i) { + ASSERT(currentSegment->data()[i]); + vector[count++] = currentSegment->data()[i]; + } + + currentSegment = currentSegment->next(); + while (currentSegment) { + for (unsigned i = 0; i < s_segmentCapacity; ++i) { + ASSERT(currentSegment->data()[i]); + vector[count++] = currentSegment->data()[i]; + } + currentSegment = currentSegment->next(); + } +} + +template <typename T> +inline GCArraySegment<T>* GCArraySegment<T>::create() +{ + return new (NotNull, fastMalloc(blockSize)) GCArraySegment<T>(); +} + +template <typename T> +inline void GCArraySegment<T>::destroy(GCArraySegment* segment) +{ + segment->~GCArraySegment(); + fastFree(segment); +} + +template <typename T> +inline size_t GCSegmentedArray<T>::postIncTop() +{ + size_t result = m_top++; + ASSERT(result == m_segments.head()->m_top++); + return result; +} + +template <typename T> +inline size_t GCSegmentedArray<T>::preDecTop() +{ + size_t result = --m_top; + ASSERT(result == --m_segments.head()->m_top); + return result; +} + +template <typename T> +inline void GCSegmentedArray<T>::setTopForFullSegment() +{ + ASSERT(m_segments.head()->m_top == s_segmentCapacity); + m_top = s_segmentCapacity; +} + +template <typename T> +inline void GCSegmentedArray<T>::setTopForEmptySegment() +{ + ASSERT(!m_segments.head()->m_top); + m_top = 0; +} + +template <typename T> +inline size_t GCSegmentedArray<T>::top() +{ + ASSERT(m_top == m_segments.head()->m_top); + return m_top; +} + +template <typename T> +#if ASSERT_DISABLED +inline void GCSegmentedArray<T>::validatePrevious() { } +#else +inline void GCSegmentedArray<T>::validatePrevious() +{ + unsigned count = 0; + for (GCArraySegment<T>* current = m_segments.head(); current; current = current->next()) + count++; + ASSERT(m_segments.size() == m_numberOfSegments); +} +#endif + +template <typename T> +inline void GCSegmentedArray<T>::append(T value) +{ + if (m_top == s_segmentCapacity) + expand(); + m_segments.head()->data()[postIncTop()] = value; +} + +template <typename T> +inline bool GCSegmentedArray<T>::canRemoveLast() +{ + return !!m_top; +} + +template <typename T> +inline const T GCSegmentedArray<T>::removeLast() +{ + return m_segments.head()->data()[preDecTop()]; +} + +template <typename T> +inline bool GCSegmentedArray<T>::isEmpty() +{ + if (m_top) + return false; + if (m_segments.head()->next()) { + ASSERT(m_segments.head()->next()->m_top == s_segmentCapacity); + return false; + } + return true; +} + +template <typename T> +inline size_t GCSegmentedArray<T>::size() +{ + return m_top + s_segmentCapacity * (m_numberOfSegments - 1); +} + +} // namespace JSC + +#endif // GCSegmentedArrayInlines_h |