]> git.saurik.com Git - apple/javascriptcore.git/blob - heap/CopiedBlock.h
JavaScriptCore-7600.1.4.13.1.tar.gz
[apple/javascriptcore.git] / heap / CopiedBlock.h
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
29 #include "BlockAllocator.h"
30 #include "CopyWorkList.h"
31 #include "HeapBlock.h"
32 #include "JSCJSValue.h"
33 #include "Options.h"
34 #include <wtf/Atomics.h>
35 #include <wtf/OwnPtr.h>
36 #include <wtf/PassOwnPtr.h>
37
38 namespace JSC {
39
40 class CopiedSpace;
41
42 class CopiedBlock : public HeapBlock<CopiedBlock> {
43 friend class CopiedSpace;
44 friend class CopiedAllocator;
45 public:
46 static CopiedBlock* create(DeadBlock*);
47 static CopiedBlock* createNoZeroFill(DeadBlock*);
48
49 void pin();
50 bool isPinned();
51
52 bool isOld();
53 bool isOversize();
54 void didPromote();
55
56 unsigned liveBytes();
57 bool shouldReportLiveBytes(SpinLockHolder&, JSCell* owner);
58 void reportLiveBytes(SpinLockHolder&, JSCell*, CopyToken, unsigned);
59 void reportLiveBytesDuringCopying(unsigned);
60 void didSurviveGC();
61 void didEvacuateBytes(unsigned);
62 bool shouldEvacuate();
63 bool canBeRecycled();
64
65 // The payload is the region of the block that is usable for allocations.
66 char* payload();
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
81 size_t size();
82 size_t capacity();
83
84 static const size_t blockSize = 32 * KB;
85
86 bool hasWorkList();
87 CopyWorkList& workList();
88 SpinLock& workListLock() { return m_workListLock; }
89
90 private:
91 CopiedBlock(Region*);
92 void zeroFillWilderness(); // Can be called at any time to zero-fill to the end of the block.
93
94 void checkConsistency();
95
96 SpinLock m_workListLock;
97 OwnPtr<CopyWorkList> m_workList;
98
99 size_t m_remaining;
100 bool m_isPinned : 1;
101 bool m_isOld : 1;
102 unsigned m_liveBytes;
103 #ifndef NDEBUG
104 unsigned m_liveObjects;
105 #endif
106 };
107
108 inline CopiedBlock* CopiedBlock::createNoZeroFill(DeadBlock* block)
109 {
110 Region* region = block->region();
111 return new(NotNull, block) CopiedBlock(region);
112 }
113
114 inline CopiedBlock* CopiedBlock::create(DeadBlock* block)
115 {
116 CopiedBlock* newBlock = createNoZeroFill(block);
117 newBlock->zeroFillWilderness();
118 return newBlock;
119 }
120
121 inline void CopiedBlock::zeroFillWilderness()
122 {
123 #if USE(JSVALUE64)
124 memset(wilderness(), 0, wildernessSize());
125 #else
126 JSValue emptyValue;
127 JSValue* limit = reinterpret_cast_ptr<JSValue*>(wildernessEnd());
128 for (JSValue* currentValue = reinterpret_cast_ptr<JSValue*>(wilderness()); currentValue < limit; currentValue++)
129 *currentValue = emptyValue;
130 #endif
131 }
132
133 inline CopiedBlock::CopiedBlock(Region* region)
134 : HeapBlock<CopiedBlock>(region)
135 , m_remaining(payloadCapacity())
136 , m_isPinned(false)
137 , m_isOld(false)
138 , m_liveBytes(0)
139 #ifndef NDEBUG
140 , m_liveObjects(0)
141 #endif
142 {
143 m_workListLock.Init();
144 ASSERT(is8ByteAligned(reinterpret_cast<void*>(m_remaining)));
145 }
146
147 inline void CopiedBlock::didSurviveGC()
148 {
149 checkConsistency();
150 ASSERT(isOld());
151 m_liveBytes = 0;
152 #ifndef NDEBUG
153 m_liveObjects = 0;
154 #endif
155 m_isPinned = false;
156 if (m_workList)
157 m_workList.clear();
158 }
159
160 inline void CopiedBlock::didEvacuateBytes(unsigned bytes)
161 {
162 ASSERT(m_liveBytes >= bytes);
163 ASSERT(m_liveObjects);
164 checkConsistency();
165 m_liveBytes -= bytes;
166 #ifndef NDEBUG
167 m_liveObjects--;
168 #endif
169 checkConsistency();
170 }
171
172 inline bool CopiedBlock::canBeRecycled()
173 {
174 checkConsistency();
175 return !m_liveBytes;
176 }
177
178 inline bool CopiedBlock::shouldEvacuate()
179 {
180 checkConsistency();
181 return static_cast<double>(m_liveBytes) / static_cast<double>(payloadCapacity()) <= Options::minCopiedBlockUtilization();
182 }
183
184 inline void CopiedBlock::pin()
185 {
186 m_isPinned = true;
187 if (m_workList)
188 m_workList.clear();
189 }
190
191 inline bool CopiedBlock::isPinned()
192 {
193 return m_isPinned;
194 }
195
196 inline bool CopiedBlock::isOld()
197 {
198 return m_isOld;
199 }
200
201 inline void CopiedBlock::didPromote()
202 {
203 m_isOld = true;
204 }
205
206 inline bool CopiedBlock::isOversize()
207 {
208 return region()->isCustomSize();
209 }
210
211 inline unsigned CopiedBlock::liveBytes()
212 {
213 checkConsistency();
214 return m_liveBytes;
215 }
216
217 inline char* CopiedBlock::payload()
218 {
219 return reinterpret_cast<char*>(this) + ((sizeof(CopiedBlock) + 7) & ~7);
220 }
221
222 inline char* CopiedBlock::payloadEnd()
223 {
224 return reinterpret_cast<char*>(this) + region()->blockSize();
225 }
226
227 inline size_t CopiedBlock::payloadCapacity()
228 {
229 return payloadEnd() - payload();
230 }
231
232 inline char* CopiedBlock::data()
233 {
234 return payload();
235 }
236
237 inline char* CopiedBlock::dataEnd()
238 {
239 return payloadEnd() - m_remaining;
240 }
241
242 inline size_t CopiedBlock::dataSize()
243 {
244 return dataEnd() - data();
245 }
246
247 inline char* CopiedBlock::wilderness()
248 {
249 return dataEnd();
250 }
251
252 inline char* CopiedBlock::wildernessEnd()
253 {
254 return payloadEnd();
255 }
256
257 inline size_t CopiedBlock::wildernessSize()
258 {
259 return wildernessEnd() - wilderness();
260 }
261
262 inline size_t CopiedBlock::size()
263 {
264 return dataSize();
265 }
266
267 inline size_t CopiedBlock::capacity()
268 {
269 return region()->blockSize();
270 }
271
272 inline bool CopiedBlock::hasWorkList()
273 {
274 return !!m_workList;
275 }
276
277 inline CopyWorkList& CopiedBlock::workList()
278 {
279 return *m_workList;
280 }
281
282 inline void CopiedBlock::checkConsistency()
283 {
284 ASSERT(!!m_liveBytes == !!m_liveObjects);
285 }
286
287 } // namespace JSC
288
289 #endif