66083a60369dd11332d258f6d4c21545fdadb643
[WebKit-https.git] / Source / JavaScriptCore / 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<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