1/*
2 * Copyright (C) 2011, 2015 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 "CopyWorkList.h"
30#include "JSCJSValue.h"
31#include "Options.h"
32#include <wtf/DoublyLinkedList.h>
33#include <wtf/Lock.h>
34
35namespace JSC {
36
37class CopiedSpace;
38
39class CopiedBlock : public DoublyLinkedListNode<CopiedBlock> {
40 friend class WTF::DoublyLinkedListNode<CopiedBlock>;
41 friend class CopiedSpace;
42 friend class CopiedAllocator;
43public:
44 static CopiedBlock* create(Heap&, size_t = blockSize);
45 static CopiedBlock* createNoZeroFill(Heap&, size_t = blockSize);
46 static void destroy(Heap&, CopiedBlock*);
47
48 void pin();
49 bool isPinned();
50
51 bool isOld();
52 bool isOversize();
53 void didPromote();
54
55 unsigned liveBytes();
56 void reportLiveBytes(LockHolder&, JSCell*, CopyToken, unsigned);
57 void reportLiveBytesDuringCopying(unsigned);
58 void didSurviveGC();
59 void didEvacuateBytes(unsigned);
60 bool shouldEvacuate();
61 bool canBeRecycled();
62
63 // The payload is the region of the block that is usable for allocations.
64 char* payload();
65 char* payloadEnd();
66 size_t payloadCapacity();
67
68 // The data is the region of the block that has been used for allocations.
69 char* data();
70 char* dataEnd();
71 size_t dataSize();
72
73 // The wilderness is the region of the block that is usable for allocations
74 // but has not been so used.
75 char* wilderness();
76 char* wildernessEnd();
77 size_t wildernessSize();
78
79 size_t size();
80 size_t capacity();
81
82 static const size_t blockSize = 32 * KB;
83
84 bool hasWorkList();
85 CopyWorkList& workList();
86 Lock& workListLock() { return m_workListLock; }
87
88private:
89 CopiedBlock(size_t);
90 void zeroFillWilderness(); // Can be called at any time to zero-fill to the end of the block.
91
92 void checkConsistency();
93
94 CopiedBlock* m_prev;
95 CopiedBlock* m_next;
96
97 size_t m_capacity;
98
99 Lock m_workListLock;
100 std::unique_ptr<CopyWorkList> m_workList;
101
102 size_t m_remaining;
103 bool m_isPinned : 1;
104 bool m_isOld : 1;
105 unsigned m_liveBytes;
106#ifndef NDEBUG
107 unsigned m_liveObjects;
108#endif
109};
110
111inline void CopiedBlock::didSurviveGC()
112{
113 checkConsistency();
114 ASSERT(isOld());
115 m_liveBytes = 0;
116#ifndef NDEBUG
117 m_liveObjects = 0;
118#endif
119 m_isPinned = false;
120 if (m_workList)
121 m_workList = nullptr;
122}
123
124inline void CopiedBlock::didEvacuateBytes(unsigned bytes)
125{
126 ASSERT(m_liveBytes >= bytes);
127 ASSERT(m_liveObjects);
128 checkConsistency();
129 m_liveBytes -= bytes;
130#ifndef NDEBUG
131 m_liveObjects--;
132#endif
133 checkConsistency();
134}
135
136inline bool CopiedBlock::canBeRecycled()
137{
138 checkConsistency();
139 return !m_liveBytes;
140}
141
142inline bool CopiedBlock::shouldEvacuate()
143{
144 checkConsistency();
145 return static_cast<double>(m_liveBytes) / static_cast<double>(payloadCapacity()) <= Options::minCopiedBlockUtilization();
146}
147
148inline void CopiedBlock::pin()
149{
150 m_isPinned = true;
151 if (m_workList)
152 m_workList = nullptr;
153}
154
155inline bool CopiedBlock::isPinned()
156{
157 return m_isPinned;
158}
159
160inline bool CopiedBlock::isOld()
161{
162 return m_isOld;
163}
164
165inline void CopiedBlock::didPromote()
166{
167 m_isOld = true;
168}
169
170inline bool CopiedBlock::isOversize()
171{
172 return m_capacity != blockSize;
173}
174
175inline unsigned CopiedBlock::liveBytes()
176{
177 checkConsistency();
178 return m_liveBytes;
179}
180
181inline char* CopiedBlock::payload()
182{
183 return reinterpret_cast<char*>(this) + WTF::roundUpToMultipleOf<sizeof(double)>(sizeof(CopiedBlock));
184}
185
186inline char* CopiedBlock::payloadEnd()
187{
188 return reinterpret_cast<char*>(this) + m_capacity;
189}
190
191inline size_t CopiedBlock::payloadCapacity()
192{
193 return payloadEnd() - payload();
194}
195
196inline char* CopiedBlock::data()
197{
198 return payload();
199}
200
201inline char* CopiedBlock::dataEnd()
202{
203 return payloadEnd() - m_remaining;
204}
205
206inline size_t CopiedBlock::dataSize()
207{
208 return dataEnd() - data();
209}
210
211inline char* CopiedBlock::wilderness()
212{
213 return dataEnd();
214}
215
216inline char* CopiedBlock::wildernessEnd()
217{
218 return payloadEnd();
219}
220
221inline size_t CopiedBlock::wildernessSize()
222{
223 return wildernessEnd() - wilderness();
224}
225
226inline size_t CopiedBlock::size()
227{
228 return dataSize();
229}
230
231inline size_t CopiedBlock::capacity()
232{
233 return m_capacity;
234}
235
236inline bool CopiedBlock::hasWorkList()
237{
238 return !!m_workList;
239}
240
241inline CopyWorkList& CopiedBlock::workList()
242{
243 return *m_workList;
244}
245
246inline void CopiedBlock::checkConsistency()
247{
248 ASSERT(!!m_liveBytes == !!m_liveObjects);
249}
250
251} // namespace JSC
252
253#endif
254