Add WTF::move()
[WebKit-https.git] / Source / JavaScriptCore / heap / HeapInlines.h
1 /*
2  * Copyright (C) 2014 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #ifndef HeapInlines_h
27 #define HeapInlines_h
28
29 #include "Heap.h"
30 #include "JSCell.h"
31 #include "Structure.h"
32
33 namespace JSC {
34
35 inline bool Heap::shouldCollect()
36 {
37     if (isDeferred())
38         return false;
39     if (Options::gcMaxHeapSize())
40         return m_bytesAllocatedThisCycle > Options::gcMaxHeapSize() && m_isSafeToCollect && m_operationInProgress == NoOperation;
41     return m_bytesAllocatedThisCycle > m_maxEdenSize && m_isSafeToCollect && m_operationInProgress == NoOperation;
42 }
43
44 inline bool Heap::isBusy()
45 {
46     return m_operationInProgress != NoOperation;
47 }
48
49 inline bool Heap::isCollecting()
50 {
51     return m_operationInProgress == FullCollection || m_operationInProgress == EdenCollection;
52 }
53
54 inline Heap* Heap::heap(const JSCell* cell)
55 {
56     return MarkedBlock::blockFor(cell)->heap();
57 }
58
59 inline Heap* Heap::heap(const JSValue v)
60 {
61     if (!v.isCell())
62         return 0;
63     return heap(v.asCell());
64 }
65
66 inline bool Heap::isLive(const void* cell)
67 {
68     return MarkedBlock::blockFor(cell)->isLiveCell(cell);
69 }
70
71 inline bool Heap::isRemembered(const void* ptr)
72 {
73     const JSCell* cell = static_cast<const JSCell*>(ptr);
74     ASSERT(cell);
75     ASSERT(!Options::enableConcurrentJIT() || !isCompilationThread());
76     ASSERT(MarkedBlock::blockFor(cell)->isRemembered(cell) == cell->isRemembered());
77     return cell->isRemembered();
78 }
79
80 inline bool Heap::isMarked(const void* cell)
81 {
82     return MarkedBlock::blockFor(cell)->isMarked(cell);
83 }
84
85 inline bool Heap::testAndSetMarked(const void* cell)
86 {
87     return MarkedBlock::blockFor(cell)->testAndSetMarked(cell);
88 }
89
90 inline void Heap::setMarked(const void* cell)
91 {
92     MarkedBlock::blockFor(cell)->setMarked(cell);
93 }
94
95 inline bool Heap::isWriteBarrierEnabled()
96 {
97 #if ENABLE(WRITE_BARRIER_PROFILING) || ENABLE(GGC)
98     return true;
99 #else
100     return false;
101 #endif
102 }
103
104 inline void Heap::writeBarrier(const JSCell* from, JSValue to)
105 {
106 #if ENABLE(WRITE_BARRIER_PROFILING)
107     WriteBarrierCounters::countWriteBarrier();
108 #endif
109 #if ENABLE(GGC)
110     if (!to.isCell())
111         return;
112     writeBarrier(from, to.asCell());
113 #else
114     UNUSED_PARAM(from);
115     UNUSED_PARAM(to);
116 #endif
117 }
118
119 inline void Heap::writeBarrier(const JSCell* from, JSCell* to)
120 {
121 #if ENABLE(WRITE_BARRIER_PROFILING)
122     WriteBarrierCounters::countWriteBarrier();
123 #endif
124 #if ENABLE(GGC)
125     if (!from || !from->isMarked()) {
126         ASSERT(!from || !isMarked(from));
127         return;
128     }
129     if (!to || to->isMarked()) {
130         ASSERT(!to || isMarked(to));
131         return;
132     }
133     addToRememberedSet(from);
134 #else
135     UNUSED_PARAM(from);
136     UNUSED_PARAM(to);
137 #endif
138 }
139
140 inline void Heap::writeBarrier(const JSCell* from)
141 {
142 #if ENABLE(GGC)
143     ASSERT_GC_OBJECT_LOOKS_VALID(const_cast<JSCell*>(from));
144     if (!from || !from->isMarked()) {
145         ASSERT(!from || !isMarked(from));
146         return;
147     }
148     ASSERT(isMarked(from));
149     addToRememberedSet(from);
150 #else
151     UNUSED_PARAM(from);
152 #endif
153 }
154
155 inline void Heap::reportExtraMemoryCost(size_t cost)
156 {
157     if (cost > minExtraCost) 
158         reportExtraMemoryCostSlowCase(cost);
159 }
160
161 template<typename Functor> inline typename Functor::ReturnType Heap::forEachProtectedCell(Functor& functor)
162 {
163     for (auto& pair : m_protectedValues)
164         functor(pair.key);
165     m_handleSet.forEachStrongHandle(functor, m_protectedValues);
166
167     return functor.returnValue();
168 }
169
170 template<typename Functor> inline typename Functor::ReturnType Heap::forEachProtectedCell()
171 {
172     Functor functor;
173     return forEachProtectedCell(functor);
174 }
175
176 template<typename Functor> inline void Heap::forEachCodeBlock(Functor& functor)
177 {
178     return m_codeBlocks.iterate<Functor>(functor);
179 }
180
181 inline void* Heap::allocateWithNormalDestructor(size_t bytes)
182 {
183 #if ENABLE(ALLOCATION_LOGGING)
184     dataLogF("JSC GC allocating %lu bytes with normal destructor.\n", bytes);
185 #endif
186     ASSERT(isValidAllocation(bytes));
187     return m_objectSpace.allocateWithNormalDestructor(bytes);
188 }
189
190 inline void* Heap::allocateWithImmortalStructureDestructor(size_t bytes)
191 {
192 #if ENABLE(ALLOCATION_LOGGING)
193     dataLogF("JSC GC allocating %lu bytes with immortal structure destructor.\n", bytes);
194 #endif
195     ASSERT(isValidAllocation(bytes));
196     return m_objectSpace.allocateWithImmortalStructureDestructor(bytes);
197 }
198
199 inline void* Heap::allocateWithoutDestructor(size_t bytes)
200 {
201 #if ENABLE(ALLOCATION_LOGGING)
202     dataLogF("JSC GC allocating %lu bytes without destructor.\n", bytes);
203 #endif
204     ASSERT(isValidAllocation(bytes));
205     return m_objectSpace.allocateWithoutDestructor(bytes);
206 }
207
208 inline CheckedBoolean Heap::tryAllocateStorage(JSCell* intendedOwner, size_t bytes, void** outPtr)
209 {
210     CheckedBoolean result = m_storageSpace.tryAllocate(bytes, outPtr);
211 #if ENABLE(ALLOCATION_LOGGING)
212     dataLogF("JSC GC allocating %lu bytes of storage for %p: %p.\n", bytes, intendedOwner, *outPtr);
213 #else
214     UNUSED_PARAM(intendedOwner);
215 #endif
216     return result;
217 }
218
219 inline CheckedBoolean Heap::tryReallocateStorage(JSCell* intendedOwner, void** ptr, size_t oldSize, size_t newSize)
220 {
221 #if ENABLE(ALLOCATION_LOGGING)
222     void* oldPtr = *ptr;
223 #endif
224     CheckedBoolean result = m_storageSpace.tryReallocate(ptr, oldSize, newSize);
225 #if ENABLE(ALLOCATION_LOGGING)
226     dataLogF("JSC GC reallocating %lu -> %lu bytes of storage for %p: %p -> %p.\n", oldSize, newSize, intendedOwner, oldPtr, *ptr);
227 #else
228     UNUSED_PARAM(intendedOwner);
229 #endif
230     return result;
231 }
232
233 inline void Heap::ascribeOwner(JSCell* intendedOwner, void* storage)
234 {
235 #if ENABLE(ALLOCATION_LOGGING)
236     dataLogF("JSC GC ascribing %p as owner of storage %p.\n", intendedOwner, storage);
237 #else
238     UNUSED_PARAM(intendedOwner);
239     UNUSED_PARAM(storage);
240 #endif
241 }
242
243 inline BlockAllocator& Heap::blockAllocator()
244 {
245     return m_blockAllocator;
246 }
247
248 #if USE(CF)
249 template <typename T>
250 inline void Heap::releaseSoon(RetainPtr<T>&& object)
251 {
252     m_objectSpace.releaseSoon(WTF::move(object));
253 }
254 #endif
255
256 inline void Heap::incrementDeferralDepth()
257 {
258     RELEASE_ASSERT(m_deferralDepth < 100); // Sanity check to make sure this doesn't get ridiculous.
259     m_deferralDepth++;
260 }
261
262 inline void Heap::decrementDeferralDepth()
263 {
264     RELEASE_ASSERT(m_deferralDepth >= 1);
265     m_deferralDepth--;
266 }
267
268 inline bool Heap::collectIfNecessaryOrDefer()
269 {
270     if (isDeferred())
271         return false;
272
273     if (!shouldCollect())
274         return false;
275
276     collect();
277     return true;
278 }
279
280 inline void Heap::decrementDeferralDepthAndGCIfNeeded()
281 {
282     decrementDeferralDepth();
283     collectIfNecessaryOrDefer();
284 }
285
286 inline HashSet<MarkedArgumentBuffer*>& Heap::markListSet()
287 {
288     if (!m_markListSet)
289         m_markListSet = adoptPtr(new HashSet<MarkedArgumentBuffer*>); 
290     return *m_markListSet;
291 }
292     
293 } // namespace JSC
294
295 #endif // HeapInlines_h