2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 * Copyright (C) 2003-2009, 2013-2014 Apple Inc. All rights reserved.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "ArrayBuffer.h"
26 #include "CodeBlockSet.h"
27 #include "CopyVisitor.h"
28 #include "GCIncomingRefCountedSet.h"
29 #include "GCThreadSharedData.h"
30 #include "HandleSet.h"
31 #include "HandleStack.h"
32 #include "HeapOperation.h"
33 #include "JITStubRoutineSet.h"
34 #include "MarkedAllocator.h"
35 #include "MarkedBlock.h"
36 #include "MarkedBlockSet.h"
37 #include "MarkedSpace.h"
39 #include "SlotVisitor.h"
40 #include "StructureIDTable.h"
41 #include "WeakHandleOwner.h"
42 #include "WriteBarrierBuffer.h"
43 #include "WriteBarrierSupport.h"
44 #include <wtf/HashCountedSet.h>
45 #include <wtf/HashSet.h>
52 class EdenGCActivityCallback
;
53 class FullGCActivityCallback
;
54 class GCActivityCallback
;
55 class GCAwareJITStubRoutine
;
56 class GlobalCodeBlock
;
58 class HeapRootVisitor
;
60 class IncrementalSweeper
;
66 class LiveObjectIterator
;
67 class LLIntOffsetsExtractor
;
68 class MarkedArgumentBuffer
;
69 class WeakGCHandlePool
;
76 static void* const zombifiedBits
= reinterpret_cast<void*>(0xdeadbeef);
78 typedef HashCountedSet
<JSCell
*> ProtectCountSet
;
79 typedef HashCountedSet
<const char*> TypeCountSet
;
81 enum HeapType
{ SmallHeap
, LargeHeap
};
84 WTF_MAKE_NONCOPYABLE(Heap
);
87 friend class DFG::SpeculativeJIT
;
88 friend class GCThreadSharedData
;
89 static Heap
* heap(const JSValue
); // 0 for immediate values
90 static Heap
* heap(const JSCell
*);
92 // This constant determines how many blocks we iterate between checks of our
93 // deadline when calling Heap::isPagedOut. Decreasing it will cause us to detect
94 // overstepping our deadline more quickly, while increasing it will cause
95 // our scan to run faster.
96 static const unsigned s_timeCheckResolution
= 16;
98 static bool isLive(const void*);
99 static bool isMarked(const void*);
100 static bool testAndSetMarked(const void*);
101 static void setMarked(const void*);
102 static bool isRemembered(const void*);
104 JS_EXPORT_PRIVATE
void addToRememberedSet(const JSCell
*);
105 static bool isWriteBarrierEnabled();
106 void writeBarrier(const JSCell
*);
107 void writeBarrier(const JSCell
*, JSValue
);
108 void writeBarrier(const JSCell
*, JSCell
*);
110 WriteBarrierBuffer
& writeBarrierBuffer() { return m_writeBarrierBuffer
; }
111 void flushWriteBarrierBuffer(JSCell
*);
115 JS_EXPORT_PRIVATE
void lastChanceToFinalize();
116 void releaseDelayedReleasedObjects();
118 VM
* vm() const { return m_vm
; }
119 MarkedSpace
& objectSpace() { return m_objectSpace
; }
120 CopiedSpace
& storageSpace() { return m_storageSpace
; }
121 MachineThreads
& machineThreads() { return m_machineThreads
; }
123 const SlotVisitor
& slotVisitor() const { return m_slotVisitor
; }
125 JS_EXPORT_PRIVATE GCActivityCallback
* fullActivityCallback();
126 JS_EXPORT_PRIVATE GCActivityCallback
* edenActivityCallback();
127 JS_EXPORT_PRIVATE
void setFullActivityCallback(PassRefPtr
<FullGCActivityCallback
>);
128 JS_EXPORT_PRIVATE
void setEdenActivityCallback(PassRefPtr
<EdenGCActivityCallback
>);
129 JS_EXPORT_PRIVATE
void setGarbageCollectionTimerEnabled(bool);
131 JS_EXPORT_PRIVATE IncrementalSweeper
* sweeper();
132 JS_EXPORT_PRIVATE
void setIncrementalSweeper(std::unique_ptr
<IncrementalSweeper
>);
134 // true if collection is in progress
136 HeapOperation
operationInProgress() { return m_operationInProgress
; }
137 // true if an allocation or collection is in progress
139 MarkedSpace::Subspace
& subspaceForObjectWithoutDestructor() { return m_objectSpace
.subspaceForObjectsWithoutDestructor(); }
140 MarkedSpace::Subspace
& subspaceForObjectDestructor() { return m_objectSpace
.subspaceForObjectsWithDestructor(); }
141 template<typename ClassType
> MarkedSpace::Subspace
& subspaceForObjectOfType();
142 MarkedAllocator
& allocatorForObjectWithoutDestructor(size_t bytes
) { return m_objectSpace
.allocatorFor(bytes
); }
143 MarkedAllocator
& allocatorForObjectWithDestructor(size_t bytes
) { return m_objectSpace
.destructorAllocatorFor(bytes
); }
144 template<typename ClassType
> MarkedAllocator
& allocatorForObjectOfType(size_t bytes
);
145 CopiedAllocator
& storageAllocator() { return m_storageSpace
.allocator(); }
146 CheckedBoolean
tryAllocateStorage(JSCell
* intendedOwner
, size_t, void**);
147 CheckedBoolean
tryReallocateStorage(JSCell
* intendedOwner
, void**, size_t, size_t);
148 void ascribeOwner(JSCell
* intendedOwner
, void*);
150 typedef void (*Finalizer
)(JSCell
*);
151 JS_EXPORT_PRIVATE
void addFinalizer(JSCell
*, Finalizer
);
152 void addCompiledCode(ExecutableBase
*);
154 void notifyIsSafeToCollect() { m_isSafeToCollect
= true; }
155 bool isSafeToCollect() const { return m_isSafeToCollect
; }
157 JS_EXPORT_PRIVATE
void collectAllGarbageIfNotDoneRecently();
158 void collectAllGarbage() { collectAndSweep(FullCollection
); }
159 JS_EXPORT_PRIVATE
void collectAndSweep(HeapOperation collectionType
= AnyCollection
);
160 bool shouldCollect();
161 JS_EXPORT_PRIVATE
void collect(HeapOperation collectionType
= AnyCollection
);
162 bool collectIfNecessaryOrDefer(); // Returns true if it did collect.
164 // Use this API to report non-GC memory referenced by GC objects. Be sure to
165 // call both of these functions: Calling only one may trigger catastropic
167 void reportExtraMemoryAllocated(size_t);
168 void reportExtraMemoryVisited(JSCell
*, size_t);
170 // Use this API to report non-GC memory if you can't use the better API above.
171 void deprecatedReportExtraMemory(size_t);
173 JS_EXPORT_PRIVATE
void reportAbandonedObjectGraph();
175 JS_EXPORT_PRIVATE
void protect(JSValue
);
176 JS_EXPORT_PRIVATE
bool unprotect(JSValue
); // True when the protect count drops to 0.
178 size_t extraMemorySize(); // Non-GC memory referenced by GC objects.
179 JS_EXPORT_PRIVATE
size_t size();
180 JS_EXPORT_PRIVATE
size_t capacity();
181 JS_EXPORT_PRIVATE
size_t objectCount();
182 JS_EXPORT_PRIVATE
size_t globalObjectCount();
183 JS_EXPORT_PRIVATE
size_t protectedObjectCount();
184 JS_EXPORT_PRIVATE
size_t protectedGlobalObjectCount();
185 JS_EXPORT_PRIVATE
std::unique_ptr
<TypeCountSet
> protectedObjectTypeCounts();
186 JS_EXPORT_PRIVATE
std::unique_ptr
<TypeCountSet
> objectTypeCounts();
187 void showStatistics();
189 HashSet
<MarkedArgumentBuffer
*>& markListSet();
191 template<typename Functor
> typename
Functor::ReturnType
forEachProtectedCell(Functor
&);
192 template<typename Functor
> typename
Functor::ReturnType
forEachProtectedCell();
193 template<typename Functor
> void forEachCodeBlock(Functor
&);
195 HandleSet
* handleSet() { return &m_handleSet
; }
196 HandleStack
* handleStack() { return &m_handleStack
; }
198 void willStartIterating();
199 void didFinishIterating();
200 void getConservativeRegisterRoots(HashSet
<JSCell
*>& roots
);
202 double lastFullGCLength() const { return m_lastFullGCLength
; }
203 double lastEdenGCLength() const { return m_lastEdenGCLength
; }
204 void increaseLastFullGCLength(double amount
) { m_lastFullGCLength
+= amount
; }
206 size_t sizeBeforeLastEdenCollection() const { return m_sizeBeforeLastEdenCollect
; }
207 size_t sizeAfterLastEdenCollection() const { return m_sizeAfterLastEdenCollect
; }
208 size_t sizeBeforeLastFullCollection() const { return m_sizeBeforeLastFullCollect
; }
209 size_t sizeAfterLastFullCollection() const { return m_sizeAfterLastFullCollect
; }
211 JS_EXPORT_PRIVATE
void deleteAllCompiledCode();
212 void deleteAllUnlinkedFunctionCode();
214 void didAllocate(size_t);
215 void didAbandon(size_t);
217 bool isPagedOut(double deadline
);
219 const JITStubRoutineSet
& jitStubRoutines() { return m_jitStubRoutines
; }
221 void addReference(JSCell
*, ArrayBuffer
*);
223 bool isDeferred() const { return !!m_deferralDepth
|| Options::disableGC(); }
225 StructureIDTable
& structureIDTable() { return m_structureIDTable
; }
228 template<typename T
> void releaseSoon(RetainPtr
<T
>&&);
231 void removeCodeBlock(CodeBlock
* cb
) { m_codeBlocks
.remove(cb
); }
233 static bool isZombified(JSCell
* cell
) { return *(void**)cell
== zombifiedBits
; }
235 void registerWeakGCMap(void* weakGCMap
, std::function
<void()> pruningCallback
);
236 void unregisterWeakGCMap(void* weakGCMap
);
238 void addLogicallyEmptyWeakBlock(WeakBlock
*);
241 friend class CodeBlock
;
242 friend class CopiedBlock
;
243 friend class DeferGC
;
244 friend class DeferGCForAWhile
;
245 friend class GCAwareJITStubRoutine
;
246 friend class GCLogging
;
247 friend class HandleSet
;
248 friend class HeapVerifier
;
249 friend class JITStubRoutine
;
250 friend class LLIntOffsetsExtractor
;
251 friend class MarkedSpace
;
252 friend class MarkedAllocator
;
253 friend class MarkedBlock
;
254 friend class CopiedSpace
;
255 friend class CopyVisitor
;
256 friend class RecursiveAllocationScope
;
257 friend class SlotVisitor
;
258 friend class SuperRegion
;
259 friend class IncrementalSweeper
;
260 friend class HeapStatistics
;
262 friend class WeakSet
;
263 template<typename T
> friend void* allocateCell(Heap
&);
264 template<typename T
> friend void* allocateCell(Heap
&, size_t);
266 void* allocateWithDestructor(size_t); // For use with objects with destructors.
267 void* allocateWithoutDestructor(size_t); // For use with objects without destructors.
268 template<typename ClassType
> void* allocateObjectOfType(size_t); // Chooses one of the methods above based on type.
270 static const size_t minExtraMemory
= 256;
272 class FinalizerOwner
: public WeakHandleOwner
{
273 virtual void finalize(Handle
<Unknown
>, void* context
) override
;
276 JS_EXPORT_PRIVATE
bool isValidAllocation(size_t);
277 JS_EXPORT_PRIVATE
void reportExtraMemoryAllocatedSlowCase(size_t);
278 JS_EXPORT_PRIVATE
void deprecatedReportExtraMemorySlowCase(size_t);
280 void collectImpl(HeapOperation
, void* stackOrigin
, void* stackTop
, MachineThreads::RegisterState
&);
282 void suspendCompilerThreads();
283 void willStartCollection(HeapOperation collectionType
);
284 void deleteOldCode(double gcStartTime
);
285 void flushOldStructureIDTables();
286 void flushWriteBarrierBuffer();
287 void stopAllocation();
289 void markRoots(double gcStartTime
, void* stackOrigin
, void* stackTop
, MachineThreads::RegisterState
&);
290 void gatherStackRoots(ConservativeRoots
&, void* stackOrigin
, void* stackTop
, MachineThreads::RegisterState
&);
291 void gatherJSStackRoots(ConservativeRoots
&);
292 void gatherScratchBufferRoots(ConservativeRoots
&);
293 void clearLivenessData();
294 void visitExternalRememberedSet();
295 void visitSmallStrings();
296 void visitConservativeRoots(ConservativeRoots
&);
297 void visitCompilerWorklistWeakReferences();
298 void removeDeadCompilerWorklistEntries();
299 void visitProtectedObjects(HeapRootVisitor
&);
300 void visitArgumentBuffers(HeapRootVisitor
&);
301 void visitException(HeapRootVisitor
&);
302 void visitStrongHandles(HeapRootVisitor
&);
303 void visitHandleStack(HeapRootVisitor
&);
304 void traceCodeBlocksAndJITStubRoutines();
306 void visitWeakHandles(HeapRootVisitor
&);
307 void clearRememberedSet(Vector
<const JSCell
*>&);
308 void updateObjectCounts(double gcStartTime
);
309 void resetVisitors();
311 void reapWeakHandles();
312 void pruneStaleEntriesFromWeakGCMaps();
313 void sweepArrayBuffers();
314 void snapshotMarkedSpace();
315 void deleteSourceProviderCaches();
316 void notifyIncrementalSweeper();
317 void rememberCurrentlyExecutingCodeBlocks();
318 void resetAllocators();
319 void copyBackingStores();
320 void harvestWeakReferences();
321 void finalizeUnconditionalFinalizers();
322 void clearUnmarkedExecutables();
323 void deleteUnmarkedCompiledCode();
324 void updateAllocationLimits();
325 void didFinishCollection(double gcStartTime
);
326 void resumeCompilerThreads();
327 void zombifyDeadObjects();
328 void markDeadObjects();
330 void sweepAllLogicallyEmptyWeakBlocks();
331 bool sweepNextLogicallyEmptyWeakBlock();
333 bool shouldDoFullCollection(HeapOperation requestedCollectionType
) const;
334 size_t sizeAfterCollect();
338 void incrementDeferralDepth();
339 void decrementDeferralDepth();
340 void decrementDeferralDepthAndGCIfNeeded();
342 const HeapType m_heapType
;
343 const size_t m_ramSize
;
344 const size_t m_minBytesPerCycle
;
345 size_t m_sizeAfterLastCollect
;
346 size_t m_sizeAfterLastFullCollect
;
347 size_t m_sizeBeforeLastFullCollect
;
348 size_t m_sizeAfterLastEdenCollect
;
349 size_t m_sizeBeforeLastEdenCollect
;
351 size_t m_bytesAllocatedThisCycle
;
352 size_t m_bytesAbandonedSinceLastFullCollect
;
353 size_t m_maxEdenSize
;
354 size_t m_maxHeapSize
;
355 bool m_shouldDoFullCollection
;
356 size_t m_totalBytesVisited
;
357 size_t m_totalBytesCopied
;
359 HeapOperation m_operationInProgress
;
360 StructureIDTable m_structureIDTable
;
361 MarkedSpace m_objectSpace
;
362 CopiedSpace m_storageSpace
;
363 GCIncomingRefCountedSet
<ArrayBuffer
> m_arrayBuffers
;
364 size_t m_extraMemorySize
;
365 size_t m_deprecatedExtraMemorySize
;
367 HashSet
<const JSCell
*> m_copyingRememberedSet
;
369 ProtectCountSet m_protectedValues
;
370 std::unique_ptr
<HashSet
<MarkedArgumentBuffer
*>> m_markListSet
;
372 MachineThreads m_machineThreads
;
374 GCThreadSharedData m_sharedData
;
375 SlotVisitor m_slotVisitor
;
376 CopyVisitor m_copyVisitor
;
378 HandleSet m_handleSet
;
379 HandleStack m_handleStack
;
380 CodeBlockSet m_codeBlocks
;
381 JITStubRoutineSet m_jitStubRoutines
;
382 FinalizerOwner m_finalizerOwner
;
384 bool m_isSafeToCollect
;
386 WriteBarrierBuffer m_writeBarrierBuffer
;
389 double m_lastFullGCLength
;
390 double m_lastEdenGCLength
;
391 double m_lastCodeDiscardTime
;
393 Vector
<ExecutableBase
*> m_compiledCode
;
395 Vector
<WeakBlock
*> m_logicallyEmptyWeakBlocks
;
396 size_t m_indexOfNextLogicallyEmptyWeakBlockToSweep
{ WTF::notFound
};
398 RefPtr
<FullGCActivityCallback
> m_fullActivityCallback
;
399 RefPtr
<GCActivityCallback
> m_edenActivityCallback
;
400 std::unique_ptr
<IncrementalSweeper
> m_sweeper
;
401 Vector
<MarkedBlock
*> m_blockSnapshot
;
403 unsigned m_deferralDepth
;
404 Vector
<DFG::Worklist
*> m_suspendedCompilerWorklists
;
406 std::unique_ptr
<HeapVerifier
> m_verifier
;
408 Vector
<RetainPtr
<CFTypeRef
>> m_delayedReleaseObjects
;
409 unsigned m_delayedReleaseRecursionCount
;
412 HashMap
<void*, std::function
<void()>> m_weakGCMaps
;