/* * 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 GCSegmentedArray::GCSegmentedArray() : m_top(0) , m_numberOfSegments(0) { m_segments.push(GCArraySegment::create()); m_numberOfSegments++; } template GCSegmentedArray::~GCSegmentedArray() { ASSERT(m_numberOfSegments == 1); ASSERT(m_segments.size() == 1); GCArraySegment::destroy(m_segments.removeHead()); m_numberOfSegments--; ASSERT(!m_numberOfSegments); ASSERT(!m_segments.size()); } template void GCSegmentedArray::clear() { if (!m_segments.head()) return; GCArraySegment* next; for (GCArraySegment* current = m_segments.head(); current->next(); current = next) { next = current->next(); m_segments.remove(current); GCArraySegment::destroy(current); } m_top = 0; m_numberOfSegments = 1; #if !ASSERT_DISABLED m_segments.head()->m_top = 0; #endif } template void GCSegmentedArray::expand() { ASSERT(m_segments.head()->m_top == s_segmentCapacity); GCArraySegment* nextSegment = GCArraySegment::create(); m_numberOfSegments++; #if !ASSERT_DISABLED nextSegment->m_top = 0; #endif m_segments.push(nextSegment); setTopForEmptySegment(); validatePrevious(); } template bool GCSegmentedArray::refill() { validatePrevious(); if (top()) return true; GCArraySegment::destroy(m_segments.removeHead()); ASSERT(m_numberOfSegments > 1); m_numberOfSegments--; setTopForFullSegment(); validatePrevious(); return true; } template void GCSegmentedArray::fillVector(Vector& vector) { ASSERT(vector.size() == size()); GCArraySegment* 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 inline GCArraySegment* GCArraySegment::create() { return new (NotNull, fastMalloc(blockSize)) GCArraySegment(); } template inline void GCArraySegment::destroy(GCArraySegment* segment) { segment->~GCArraySegment(); fastFree(segment); } template inline size_t GCSegmentedArray::postIncTop() { size_t result = m_top++; ASSERT(result == m_segments.head()->m_top++); return result; } template inline size_t GCSegmentedArray::preDecTop() { size_t result = --m_top; ASSERT(result == --m_segments.head()->m_top); return result; } template inline void GCSegmentedArray::setTopForFullSegment() { ASSERT(m_segments.head()->m_top == s_segmentCapacity); m_top = s_segmentCapacity; } template inline void GCSegmentedArray::setTopForEmptySegment() { ASSERT(!m_segments.head()->m_top); m_top = 0; } template inline size_t GCSegmentedArray::top() { ASSERT(m_top == m_segments.head()->m_top); return m_top; } template #if ASSERT_DISABLED inline void GCSegmentedArray::validatePrevious() { } #else inline void GCSegmentedArray::validatePrevious() { unsigned count = 0; for (GCArraySegment* current = m_segments.head(); current; current = current->next()) count++; ASSERT(m_segments.size() == m_numberOfSegments); } #endif template inline void GCSegmentedArray::append(T value) { if (m_top == s_segmentCapacity) expand(); m_segments.head()->data()[postIncTop()] = value; } template inline bool GCSegmentedArray::canRemoveLast() { return !!m_top; } template inline const T GCSegmentedArray::removeLast() { return m_segments.head()->data()[preDecTop()]; } template inline bool GCSegmentedArray::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 inline size_t GCSegmentedArray::size() { return m_top + s_segmentCapacity * (m_numberOfSegments - 1); } } // namespace JSC #endif // GCSegmentedArrayInlines_h