]> git.saurik.com Git - apple/javascriptcore.git/blame - heap/GCSegmentedArrayInlines.h
JavaScriptCore-7600.1.4.16.1.tar.gz
[apple/javascriptcore.git] / heap / GCSegmentedArrayInlines.h
CommitLineData
81345200
A
1/*
2 * Copyright (C) 2014 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef GCSegmentedArrayInlines_h
27#define GCSegmentedArrayInlines_h
28
29#include "BlockAllocator.h"
30#include "GCSegmentedArray.h"
31
32namespace JSC {
33
34template <typename T>
35GCSegmentedArray<T>::GCSegmentedArray(BlockAllocator& blockAllocator)
36 : m_blockAllocator(blockAllocator)
37 , m_top(0)
38 , m_numberOfSegments(0)
39{
40 m_segments.push(GCArraySegment<T>::create(m_blockAllocator.allocate<GCArraySegment<T>>()));
41 m_numberOfSegments++;
42}
43
44template <typename T>
45GCSegmentedArray<T>::~GCSegmentedArray()
46{
47 ASSERT(m_numberOfSegments == 1);
48 ASSERT(m_segments.size() == 1);
49 m_blockAllocator.deallocate(GCArraySegment<T>::destroy(m_segments.removeHead()));
50 m_numberOfSegments--;
51 ASSERT(!m_numberOfSegments);
52 ASSERT(!m_segments.size());
53}
54
55template <typename T>
56void GCSegmentedArray<T>::clear()
57{
58 if (!m_segments.head())
59 return;
60 GCArraySegment<T>* next;
61 for (GCArraySegment<T>* current = m_segments.head(); current->next(); current = next) {
62 next = current->next();
63 m_segments.remove(current);
64 m_blockAllocator.deallocate(GCArraySegment<T>::destroy(current));
65 }
66 m_top = 0;
67 m_numberOfSegments = 1;
68#if !ASSERT_DISABLED
69 m_segments.head()->m_top = 0;
70#endif
71}
72
73template <typename T>
74void GCSegmentedArray<T>::expand()
75{
76 ASSERT(m_segments.head()->m_top == s_segmentCapacity);
77
78 GCArraySegment<T>* nextSegment = GCArraySegment<T>::create(m_blockAllocator.allocate<GCArraySegment<T>>());
79 m_numberOfSegments++;
80
81#if !ASSERT_DISABLED
82 nextSegment->m_top = 0;
83#endif
84
85 m_segments.push(nextSegment);
86 setTopForEmptySegment();
87 validatePrevious();
88}
89
90template <typename T>
91bool GCSegmentedArray<T>::refill()
92{
93 validatePrevious();
94 if (top())
95 return true;
96 m_blockAllocator.deallocate(GCArraySegment<T>::destroy(m_segments.removeHead()));
97 ASSERT(m_numberOfSegments > 1);
98 m_numberOfSegments--;
99 setTopForFullSegment();
100 validatePrevious();
101 return true;
102}
103
104template <typename T>
105void GCSegmentedArray<T>::fillVector(Vector<T>& vector)
106{
107 ASSERT(vector.size() == size());
108
109 GCArraySegment<T>* currentSegment = m_segments.head();
110 if (!currentSegment)
111 return;
112
113 unsigned count = 0;
114 for (unsigned i = 0; i < m_top; ++i) {
115 ASSERT(currentSegment->data()[i]);
116 vector[count++] = currentSegment->data()[i];
117 }
118
119 currentSegment = currentSegment->next();
120 while (currentSegment) {
121 for (unsigned i = 0; i < s_segmentCapacity; ++i) {
122 ASSERT(currentSegment->data()[i]);
123 vector[count++] = currentSegment->data()[i];
124 }
125 currentSegment = currentSegment->next();
126 }
127}
128
129template <typename T>
130inline GCArraySegment<T>* GCArraySegment<T>::create(DeadBlock* block)
131{
132 return new (NotNull, block) GCArraySegment<T>(block->region());
133}
134
135template <typename T>
136inline size_t GCSegmentedArray<T>::postIncTop()
137{
138 size_t result = m_top++;
139 ASSERT(result == m_segments.head()->m_top++);
140 return result;
141}
142
143template <typename T>
144inline size_t GCSegmentedArray<T>::preDecTop()
145{
146 size_t result = --m_top;
147 ASSERT(result == --m_segments.head()->m_top);
148 return result;
149}
150
151template <typename T>
152inline void GCSegmentedArray<T>::setTopForFullSegment()
153{
154 ASSERT(m_segments.head()->m_top == s_segmentCapacity);
155 m_top = s_segmentCapacity;
156}
157
158template <typename T>
159inline void GCSegmentedArray<T>::setTopForEmptySegment()
160{
161 ASSERT(!m_segments.head()->m_top);
162 m_top = 0;
163}
164
165template <typename T>
166inline size_t GCSegmentedArray<T>::top()
167{
168 ASSERT(m_top == m_segments.head()->m_top);
169 return m_top;
170}
171
172template <typename T>
173#if ASSERT_DISABLED
174inline void GCSegmentedArray<T>::validatePrevious() { }
175#else
176inline void GCSegmentedArray<T>::validatePrevious()
177{
178 unsigned count = 0;
179 for (GCArraySegment<T>* current = m_segments.head(); current; current = current->next())
180 count++;
181 ASSERT(m_segments.size() == m_numberOfSegments);
182}
183#endif
184
185template <typename T>
186inline void GCSegmentedArray<T>::append(T value)
187{
188 if (m_top == s_segmentCapacity)
189 expand();
190 m_segments.head()->data()[postIncTop()] = value;
191}
192
193template <typename T>
194inline bool GCSegmentedArray<T>::canRemoveLast()
195{
196 return !!m_top;
197}
198
199template <typename T>
200inline const T GCSegmentedArray<T>::removeLast()
201{
202 return m_segments.head()->data()[preDecTop()];
203}
204
205template <typename T>
206inline bool GCSegmentedArray<T>::isEmpty()
207{
208 if (m_top)
209 return false;
210 if (m_segments.head()->next()) {
211 ASSERT(m_segments.head()->next()->m_top == s_segmentCapacity);
212 return false;
213 }
214 return true;
215}
216
217template <typename T>
218inline size_t GCSegmentedArray<T>::size()
219{
220 return m_top + s_segmentCapacity * (m_numberOfSegments - 1);
221}
222
223} // namespace JSC
224
225#endif // GCSegmentedArrayInlines_h