]> git.saurik.com Git - apple/javascriptcore.git/blob - heap/CopiedBlock.h
JavaScriptCore-1218.34.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 isOversize();
53
54 unsigned liveBytes();
55 void reportLiveBytes(JSCell*, unsigned);
56 void didSurviveGC();
57 void didEvacuateBytes(unsigned);
58 bool shouldEvacuate();
59 bool canBeRecycled();
60
61 // The payload is the region of the block that is usable for allocations.
62 char* payload();
63 char* payloadEnd();
64 size_t payloadCapacity();
65
66 // The data is the region of the block that has been used for allocations.
67 char* data();
68 char* dataEnd();
69 size_t dataSize();
70
71 // The wilderness is the region of the block that is usable for allocations
72 // but has not been so used.
73 char* wilderness();
74 char* wildernessEnd();
75 size_t wildernessSize();
76
77 size_t size();
78 size_t capacity();
79
80 static const size_t blockSize = 32 * KB;
81
82 bool hasWorkList();
83 CopyWorkList& workList();
84
85 private:
86 CopiedBlock(Region*);
87 void zeroFillWilderness(); // Can be called at any time to zero-fill to the end of the block.
88
89 #if ENABLE(PARALLEL_GC)
90 SpinLock m_workListLock;
91 #endif
92 OwnPtr<CopyWorkList> m_workList;
93
94 size_t m_remaining;
95 uintptr_t m_isPinned;
96 unsigned m_liveBytes;
97 };
98
99 inline CopiedBlock* CopiedBlock::createNoZeroFill(DeadBlock* block)
100 {
101 Region* region = block->region();
102 return new(NotNull, block) CopiedBlock(region);
103 }
104
105 inline CopiedBlock* CopiedBlock::create(DeadBlock* block)
106 {
107 CopiedBlock* newBlock = createNoZeroFill(block);
108 newBlock->zeroFillWilderness();
109 return newBlock;
110 }
111
112 inline void CopiedBlock::zeroFillWilderness()
113 {
114 #if USE(JSVALUE64)
115 memset(wilderness(), 0, wildernessSize());
116 #else
117 JSValue emptyValue;
118 JSValue* limit = reinterpret_cast_ptr<JSValue*>(wildernessEnd());
119 for (JSValue* currentValue = reinterpret_cast_ptr<JSValue*>(wilderness()); currentValue < limit; currentValue++)
120 *currentValue = emptyValue;
121 #endif
122 }
123
124 inline CopiedBlock::CopiedBlock(Region* region)
125 : HeapBlock<CopiedBlock>(region)
126 , m_remaining(payloadCapacity())
127 , m_isPinned(false)
128 , m_liveBytes(0)
129 {
130 #if ENABLE(PARALLEL_GC)
131 m_workListLock.Init();
132 #endif
133 ASSERT(is8ByteAligned(reinterpret_cast<void*>(m_remaining)));
134 }
135
136 inline void CopiedBlock::didSurviveGC()
137 {
138 m_liveBytes = 0;
139 m_isPinned = false;
140 if (m_workList)
141 m_workList.clear();
142 }
143
144 inline void CopiedBlock::didEvacuateBytes(unsigned bytes)
145 {
146 ASSERT(m_liveBytes >= bytes);
147 m_liveBytes -= bytes;
148 }
149
150 inline bool CopiedBlock::canBeRecycled()
151 {
152 return !m_liveBytes;
153 }
154
155 inline bool CopiedBlock::shouldEvacuate()
156 {
157 return static_cast<double>(m_liveBytes) / static_cast<double>(payloadCapacity()) <= Options::minCopiedBlockUtilization();
158 }
159
160 inline void CopiedBlock::pin()
161 {
162 m_isPinned = true;
163 if (m_workList)
164 m_workList.clear();
165 }
166
167 inline bool CopiedBlock::isPinned()
168 {
169 return m_isPinned;
170 }
171
172 inline bool CopiedBlock::isOversize()
173 {
174 return region()->isCustomSize();
175 }
176
177 inline unsigned CopiedBlock::liveBytes()
178 {
179 return m_liveBytes;
180 }
181
182 inline char* CopiedBlock::payload()
183 {
184 return reinterpret_cast<char*>(this) + ((sizeof(CopiedBlock) + 7) & ~7);
185 }
186
187 inline char* CopiedBlock::payloadEnd()
188 {
189 return reinterpret_cast<char*>(this) + region()->blockSize();
190 }
191
192 inline size_t CopiedBlock::payloadCapacity()
193 {
194 return payloadEnd() - payload();
195 }
196
197 inline char* CopiedBlock::data()
198 {
199 return payload();
200 }
201
202 inline char* CopiedBlock::dataEnd()
203 {
204 return payloadEnd() - m_remaining;
205 }
206
207 inline size_t CopiedBlock::dataSize()
208 {
209 return dataEnd() - data();
210 }
211
212 inline char* CopiedBlock::wilderness()
213 {
214 return dataEnd();
215 }
216
217 inline char* CopiedBlock::wildernessEnd()
218 {
219 return payloadEnd();
220 }
221
222 inline size_t CopiedBlock::wildernessSize()
223 {
224 return wildernessEnd() - wilderness();
225 }
226
227 inline size_t CopiedBlock::size()
228 {
229 return dataSize();
230 }
231
232 inline size_t CopiedBlock::capacity()
233 {
234 return region()->blockSize();
235 }
236
237 inline bool CopiedBlock::hasWorkList()
238 {
239 return !!m_workList;
240 }
241
242 inline CopyWorkList& CopiedBlock::workList()
243 {
244 return *m_workList;
245 }
246
247 } // namespace JSC
248
249 #endif