]>
Commit | Line | Data |
---|---|---|
6fe7ccc8 A |
1 | /* |
2 | * Copyright (C) 2011 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. ``AS IS'' AND ANY | |
14 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR | |
17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
20 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
21 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
23 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | */ | |
25 | ||
26 | #ifndef CopiedBlock_h | |
27 | #define CopiedBlock_h | |
28 | ||
93a37866 | 29 | #include "CopyWorkList.h" |
93a37866 A |
30 | #include "JSCJSValue.h" |
31 | #include "Options.h" | |
32 | #include <wtf/Atomics.h> | |
ed1e77d3 A |
33 | #include <wtf/DoublyLinkedList.h> |
34 | #include <wtf/SpinLock.h> | |
6fe7ccc8 A |
35 | |
36 | namespace JSC { | |
37 | ||
38 | class CopiedSpace; | |
39 | ||
ed1e77d3 A |
40 | class CopiedBlock : public DoublyLinkedListNode<CopiedBlock> { |
41 | friend class WTF::DoublyLinkedListNode<CopiedBlock>; | |
6fe7ccc8 A |
42 | friend class CopiedSpace; |
43 | friend class CopiedAllocator; | |
44 | public: | |
ed1e77d3 A |
45 | static CopiedBlock* create(size_t = blockSize); |
46 | static CopiedBlock* createNoZeroFill(size_t = blockSize); | |
47 | static void destroy(CopiedBlock*); | |
93a37866 A |
48 | |
49 | void pin(); | |
50 | bool isPinned(); | |
51 | ||
81345200 | 52 | bool isOld(); |
93a37866 | 53 | bool isOversize(); |
81345200 | 54 | void didPromote(); |
93a37866 A |
55 | |
56 | unsigned liveBytes(); | |
81345200 A |
57 | bool shouldReportLiveBytes(SpinLockHolder&, JSCell* owner); |
58 | void reportLiveBytes(SpinLockHolder&, JSCell*, CopyToken, unsigned); | |
59 | void reportLiveBytesDuringCopying(unsigned); | |
93a37866 A |
60 | void didSurviveGC(); |
61 | void didEvacuateBytes(unsigned); | |
62 | bool shouldEvacuate(); | |
63 | bool canBeRecycled(); | |
6fe7ccc8 | 64 | |
93a37866 | 65 | // The payload is the region of the block that is usable for allocations. |
6fe7ccc8 | 66 | char* payload(); |
93a37866 A |
67 | char* payloadEnd(); |
68 | size_t payloadCapacity(); | |
69 | ||
70 | // The data is the region of the block that has been used for allocations. | |
71 | char* data(); | |
72 | char* dataEnd(); | |
73 | size_t dataSize(); | |
74 | ||
75 | // The wilderness is the region of the block that is usable for allocations | |
76 | // but has not been so used. | |
77 | char* wilderness(); | |
78 | char* wildernessEnd(); | |
79 | size_t wildernessSize(); | |
80 | ||
6fe7ccc8 A |
81 | size_t size(); |
82 | size_t capacity(); | |
83 | ||
93a37866 A |
84 | static const size_t blockSize = 32 * KB; |
85 | ||
86 | bool hasWorkList(); | |
87 | CopyWorkList& workList(); | |
81345200 | 88 | SpinLock& workListLock() { return m_workListLock; } |
93a37866 | 89 | |
6fe7ccc8 | 90 | private: |
ed1e77d3 | 91 | CopiedBlock(size_t); |
93a37866 A |
92 | void zeroFillWilderness(); // Can be called at any time to zero-fill to the end of the block. |
93 | ||
81345200 A |
94 | void checkConsistency(); |
95 | ||
ed1e77d3 A |
96 | CopiedBlock* m_prev; |
97 | CopiedBlock* m_next; | |
98 | ||
99 | size_t m_capacity; | |
100 | ||
93a37866 | 101 | SpinLock m_workListLock; |
ed1e77d3 | 102 | std::unique_ptr<CopyWorkList> m_workList; |
93a37866 A |
103 | |
104 | size_t m_remaining; | |
81345200 A |
105 | bool m_isPinned : 1; |
106 | bool m_isOld : 1; | |
93a37866 | 107 | unsigned m_liveBytes; |
81345200 A |
108 | #ifndef NDEBUG |
109 | unsigned m_liveObjects; | |
110 | #endif | |
6fe7ccc8 A |
111 | }; |
112 | ||
ed1e77d3 A |
113 | inline CopiedBlock* CopiedBlock::createNoZeroFill(size_t capacity) |
114 | { | |
115 | return new(NotNull, fastAlignedMalloc(CopiedBlock::blockSize, capacity)) CopiedBlock(capacity); | |
116 | } | |
117 | ||
118 | inline void CopiedBlock::destroy(CopiedBlock* copiedBlock) | |
93a37866 | 119 | { |
ed1e77d3 A |
120 | copiedBlock->~CopiedBlock(); |
121 | fastAlignedFree(copiedBlock); | |
93a37866 A |
122 | } |
123 | ||
ed1e77d3 | 124 | inline CopiedBlock* CopiedBlock::create(size_t capacity) |
93a37866 | 125 | { |
ed1e77d3 | 126 | CopiedBlock* newBlock = createNoZeroFill(capacity); |
93a37866 A |
127 | newBlock->zeroFillWilderness(); |
128 | return newBlock; | |
129 | } | |
130 | ||
131 | inline void CopiedBlock::zeroFillWilderness() | |
132 | { | |
133 | #if USE(JSVALUE64) | |
134 | memset(wilderness(), 0, wildernessSize()); | |
135 | #else | |
136 | JSValue emptyValue; | |
137 | JSValue* limit = reinterpret_cast_ptr<JSValue*>(wildernessEnd()); | |
138 | for (JSValue* currentValue = reinterpret_cast_ptr<JSValue*>(wilderness()); currentValue < limit; currentValue++) | |
139 | *currentValue = emptyValue; | |
140 | #endif | |
141 | } | |
142 | ||
ed1e77d3 A |
143 | inline CopiedBlock::CopiedBlock(size_t capacity) |
144 | : DoublyLinkedListNode<CopiedBlock>() | |
145 | , m_capacity(capacity) | |
93a37866 A |
146 | , m_remaining(payloadCapacity()) |
147 | , m_isPinned(false) | |
81345200 | 148 | , m_isOld(false) |
93a37866 | 149 | , m_liveBytes(0) |
81345200 A |
150 | #ifndef NDEBUG |
151 | , m_liveObjects(0) | |
152 | #endif | |
93a37866 | 153 | { |
93a37866 A |
154 | ASSERT(is8ByteAligned(reinterpret_cast<void*>(m_remaining))); |
155 | } | |
156 | ||
157 | inline void CopiedBlock::didSurviveGC() | |
158 | { | |
81345200 A |
159 | checkConsistency(); |
160 | ASSERT(isOld()); | |
93a37866 | 161 | m_liveBytes = 0; |
81345200 A |
162 | #ifndef NDEBUG |
163 | m_liveObjects = 0; | |
164 | #endif | |
93a37866 A |
165 | m_isPinned = false; |
166 | if (m_workList) | |
ed1e77d3 | 167 | m_workList = nullptr; |
93a37866 A |
168 | } |
169 | ||
170 | inline void CopiedBlock::didEvacuateBytes(unsigned bytes) | |
171 | { | |
172 | ASSERT(m_liveBytes >= bytes); | |
81345200 A |
173 | ASSERT(m_liveObjects); |
174 | checkConsistency(); | |
93a37866 | 175 | m_liveBytes -= bytes; |
81345200 A |
176 | #ifndef NDEBUG |
177 | m_liveObjects--; | |
178 | #endif | |
179 | checkConsistency(); | |
93a37866 A |
180 | } |
181 | ||
182 | inline bool CopiedBlock::canBeRecycled() | |
183 | { | |
81345200 | 184 | checkConsistency(); |
93a37866 A |
185 | return !m_liveBytes; |
186 | } | |
187 | ||
188 | inline bool CopiedBlock::shouldEvacuate() | |
189 | { | |
81345200 | 190 | checkConsistency(); |
93a37866 A |
191 | return static_cast<double>(m_liveBytes) / static_cast<double>(payloadCapacity()) <= Options::minCopiedBlockUtilization(); |
192 | } | |
193 | ||
194 | inline void CopiedBlock::pin() | |
195 | { | |
196 | m_isPinned = true; | |
197 | if (m_workList) | |
ed1e77d3 | 198 | m_workList = nullptr; |
93a37866 A |
199 | } |
200 | ||
201 | inline bool CopiedBlock::isPinned() | |
202 | { | |
203 | return m_isPinned; | |
204 | } | |
205 | ||
81345200 A |
206 | inline bool CopiedBlock::isOld() |
207 | { | |
208 | return m_isOld; | |
209 | } | |
210 | ||
211 | inline void CopiedBlock::didPromote() | |
212 | { | |
213 | m_isOld = true; | |
214 | } | |
215 | ||
93a37866 A |
216 | inline bool CopiedBlock::isOversize() |
217 | { | |
ed1e77d3 | 218 | return m_capacity != blockSize; |
93a37866 A |
219 | } |
220 | ||
221 | inline unsigned CopiedBlock::liveBytes() | |
222 | { | |
81345200 | 223 | checkConsistency(); |
93a37866 A |
224 | return m_liveBytes; |
225 | } | |
226 | ||
6fe7ccc8 A |
227 | inline char* CopiedBlock::payload() |
228 | { | |
ed1e77d3 | 229 | return reinterpret_cast<char*>(this) + WTF::roundUpToMultipleOf<sizeof(double)>(sizeof(CopiedBlock)); |
6fe7ccc8 A |
230 | } |
231 | ||
93a37866 A |
232 | inline char* CopiedBlock::payloadEnd() |
233 | { | |
ed1e77d3 | 234 | return reinterpret_cast<char*>(this) + m_capacity; |
93a37866 A |
235 | } |
236 | ||
237 | inline size_t CopiedBlock::payloadCapacity() | |
238 | { | |
239 | return payloadEnd() - payload(); | |
240 | } | |
241 | ||
242 | inline char* CopiedBlock::data() | |
243 | { | |
244 | return payload(); | |
245 | } | |
246 | ||
247 | inline char* CopiedBlock::dataEnd() | |
248 | { | |
249 | return payloadEnd() - m_remaining; | |
250 | } | |
251 | ||
252 | inline size_t CopiedBlock::dataSize() | |
253 | { | |
254 | return dataEnd() - data(); | |
255 | } | |
256 | ||
257 | inline char* CopiedBlock::wilderness() | |
258 | { | |
259 | return dataEnd(); | |
260 | } | |
261 | ||
262 | inline char* CopiedBlock::wildernessEnd() | |
263 | { | |
264 | return payloadEnd(); | |
265 | } | |
266 | ||
267 | inline size_t CopiedBlock::wildernessSize() | |
268 | { | |
269 | return wildernessEnd() - wilderness(); | |
270 | } | |
271 | ||
6fe7ccc8 A |
272 | inline size_t CopiedBlock::size() |
273 | { | |
93a37866 | 274 | return dataSize(); |
6fe7ccc8 A |
275 | } |
276 | ||
277 | inline size_t CopiedBlock::capacity() | |
278 | { | |
ed1e77d3 | 279 | return m_capacity; |
93a37866 A |
280 | } |
281 | ||
282 | inline bool CopiedBlock::hasWorkList() | |
283 | { | |
284 | return !!m_workList; | |
285 | } | |
286 | ||
287 | inline CopyWorkList& CopiedBlock::workList() | |
288 | { | |
289 | return *m_workList; | |
6fe7ccc8 A |
290 | } |
291 | ||
81345200 A |
292 | inline void CopiedBlock::checkConsistency() |
293 | { | |
294 | ASSERT(!!m_liveBytes == !!m_liveObjects); | |
295 | } | |
296 | ||
6fe7ccc8 A |
297 | } // namespace JSC |
298 | ||
299 | #endif |