]> git.saurik.com Git - apple/javascriptcore.git/blame - heap/CopiedBlock.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / heap / CopiedBlock.h
CommitLineData
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
36namespace JSC {
37
38class CopiedSpace;
39
ed1e77d3
A
40class CopiedBlock : public DoublyLinkedListNode<CopiedBlock> {
41 friend class WTF::DoublyLinkedListNode<CopiedBlock>;
6fe7ccc8
A
42 friend class CopiedSpace;
43 friend class CopiedAllocator;
44public:
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 90private:
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
113inline CopiedBlock* CopiedBlock::createNoZeroFill(size_t capacity)
114{
115 return new(NotNull, fastAlignedMalloc(CopiedBlock::blockSize, capacity)) CopiedBlock(capacity);
116}
117
118inline void CopiedBlock::destroy(CopiedBlock* copiedBlock)
93a37866 119{
ed1e77d3
A
120 copiedBlock->~CopiedBlock();
121 fastAlignedFree(copiedBlock);
93a37866
A
122}
123
ed1e77d3 124inline CopiedBlock* CopiedBlock::create(size_t capacity)
93a37866 125{
ed1e77d3 126 CopiedBlock* newBlock = createNoZeroFill(capacity);
93a37866
A
127 newBlock->zeroFillWilderness();
128 return newBlock;
129}
130
131inline 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
143inline 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
157inline 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
170inline 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
182inline bool CopiedBlock::canBeRecycled()
183{
81345200 184 checkConsistency();
93a37866
A
185 return !m_liveBytes;
186}
187
188inline bool CopiedBlock::shouldEvacuate()
189{
81345200 190 checkConsistency();
93a37866
A
191 return static_cast<double>(m_liveBytes) / static_cast<double>(payloadCapacity()) <= Options::minCopiedBlockUtilization();
192}
193
194inline void CopiedBlock::pin()
195{
196 m_isPinned = true;
197 if (m_workList)
ed1e77d3 198 m_workList = nullptr;
93a37866
A
199}
200
201inline bool CopiedBlock::isPinned()
202{
203 return m_isPinned;
204}
205
81345200
A
206inline bool CopiedBlock::isOld()
207{
208 return m_isOld;
209}
210
211inline void CopiedBlock::didPromote()
212{
213 m_isOld = true;
214}
215
93a37866
A
216inline bool CopiedBlock::isOversize()
217{
ed1e77d3 218 return m_capacity != blockSize;
93a37866
A
219}
220
221inline unsigned CopiedBlock::liveBytes()
222{
81345200 223 checkConsistency();
93a37866
A
224 return m_liveBytes;
225}
226
6fe7ccc8
A
227inline char* CopiedBlock::payload()
228{
ed1e77d3 229 return reinterpret_cast<char*>(this) + WTF::roundUpToMultipleOf<sizeof(double)>(sizeof(CopiedBlock));
6fe7ccc8
A
230}
231
93a37866
A
232inline char* CopiedBlock::payloadEnd()
233{
ed1e77d3 234 return reinterpret_cast<char*>(this) + m_capacity;
93a37866
A
235}
236
237inline size_t CopiedBlock::payloadCapacity()
238{
239 return payloadEnd() - payload();
240}
241
242inline char* CopiedBlock::data()
243{
244 return payload();
245}
246
247inline char* CopiedBlock::dataEnd()
248{
249 return payloadEnd() - m_remaining;
250}
251
252inline size_t CopiedBlock::dataSize()
253{
254 return dataEnd() - data();
255}
256
257inline char* CopiedBlock::wilderness()
258{
259 return dataEnd();
260}
261
262inline char* CopiedBlock::wildernessEnd()
263{
264 return payloadEnd();
265}
266
267inline size_t CopiedBlock::wildernessSize()
268{
269 return wildernessEnd() - wilderness();
270}
271
6fe7ccc8
A
272inline size_t CopiedBlock::size()
273{
93a37866 274 return dataSize();
6fe7ccc8
A
275}
276
277inline size_t CopiedBlock::capacity()
278{
ed1e77d3 279 return m_capacity;
93a37866
A
280}
281
282inline bool CopiedBlock::hasWorkList()
283{
284 return !!m_workList;
285}
286
287inline CopyWorkList& CopiedBlock::workList()
288{
289 return *m_workList;
6fe7ccc8
A
290}
291
81345200
A
292inline void CopiedBlock::checkConsistency()
293{
294 ASSERT(!!m_liveBytes == !!m_liveObjects);
295}
296
6fe7ccc8
A
297} // namespace JSC
298
299#endif