blob: 46fc4116db3cbab4f9fc333e825b13e5e02898d3 [file] [log] [blame]
kocienda66a6d362001-08-24 14:24:45 +00001/*
fpizlo@apple.com95ef6492016-03-15 15:26:36 +00002 * Copyright (C) 2003-2009, 2011, 2013-2016 Apple Inc. All rights reserved.
eseidelc504bad2007-10-24 21:31:27 +00003 * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
kocienda66a6d362001-08-24 14:24:45 +00004 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
mjscdff33b2006-01-23 21:41:36 +000017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
mjs6f821c82002-03-22 00:31:57 +000018 *
kocienda66a6d362001-08-24 14:24:45 +000019 */
20
mjsb64c50a2005-10-03 21:13:12 +000021#include "config.h"
ggaren@apple.coma8b38542011-01-10 23:43:56 +000022#include "Heap.h"
darinff399e02002-11-23 07:49:05 +000023
ggaren@apple.com79ab2a92011-02-02 05:05:55 +000024#include "CodeBlock.h"
fpizlo@apple.com7b231642016-10-11 23:52:02 +000025#include "CodeBlockSet.h"
ggaren@apple.com0b32d092011-04-11 21:57:31 +000026#include "ConservativeRoots.h"
oliver@apple.com284cc3d2013-07-25 04:00:33 +000027#include "DFGWorklist.h"
mhahnenberg@apple.com0d81ace2014-03-20 01:56:19 +000028#include "EdenGCActivityCallback.h"
29#include "FullGCActivityCallback.h"
ggaren@apple.com2ccf7a92010-08-03 20:34:17 +000030#include "GCActivityCallback.h"
fpizlo@apple.com0e0d9312013-08-15 20:43:06 +000031#include "GCIncomingRefCountedSetInlines.h"
fpizlo@apple.comc9f8a492016-09-24 00:47:30 +000032#include "GCSegmentedArrayInlines.h"
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000033#include "GCTypeMap.h"
sbarati@apple.coma3db4652016-09-20 01:05:50 +000034#include "HasOwnPropertyCache.h"
fpizlo@apple.com5f866062015-09-26 18:07:09 +000035#include "HeapHelperPool.h"
mhahnenberg@apple.combee96a32013-09-16 19:48:48 +000036#include "HeapIterationScope.h"
commit-queue@webkit.orgd38d0682016-03-03 05:15:56 +000037#include "HeapProfiler.h"
ggaren@apple.comd2b624b2011-05-24 23:46:35 +000038#include "HeapRootVisitor.h"
commit-queue@webkit.orgd38d0682016-03-03 05:15:56 +000039#include "HeapSnapshot.h"
mhahnenberg@apple.com3a2fb032012-10-05 17:35:49 +000040#include "HeapStatistics.h"
mark.lam@apple.com34e46672014-11-20 23:28:41 +000041#include "HeapVerifier.h"
fpizlo@apple.comea379af2016-10-21 02:17:35 +000042#include "HelpingGCScope.h"
mhahnenberg@apple.comeb39abc2012-05-31 03:04:00 +000043#include "IncrementalSweeper.h"
weinig@apple.comf5b90cd2009-01-16 00:24:24 +000044#include "Interpreter.h"
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000045#include "JITStubRoutineSet.h"
fpizlo@apple.com46050f72016-06-17 04:48:47 +000046#include "JITWorklist.h"
joepeck@webkit.org14c5caf2015-10-12 21:29:21 +000047#include "JSCInlines.h"
ggaren@apple.comf0863872007-12-03 07:53:03 +000048#include "JSGlobalObject.h"
ap@webkit.org01aff702008-08-20 07:23:06 +000049#include "JSLock.h"
mhahnenberg@apple.com1629c062014-04-15 21:05:09 +000050#include "JSVirtualMachineInternal.h"
fpizlo@apple.com96352992016-09-20 18:12:18 +000051#include "MarkedSpaceInlines.h"
sbarati@apple.coma4ce86b2016-01-11 06:49:49 +000052#include "SamplingProfiler.h"
fpizlo@apple.com39303e02016-04-05 22:17:35 +000053#include "ShadowChicken.h"
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000054#include "SuperSampler.h"
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +000055#include "TypeProfilerLog.h"
oliver@apple.comf0c01b82012-11-07 00:13:54 +000056#include "UnlinkedCodeBlock.h"
mhahnenberg@apple.com7a22bab2013-12-10 19:37:29 +000057#include "VM.h"
ggaren@apple.comab71e972012-04-28 05:57:46 +000058#include "WeakSetInlines.h"
ggaren@apple.comf2663492011-02-05 00:20:16 +000059#include <algorithm>
fpizlo@apple.com622ead72011-11-01 06:43:37 +000060#include <wtf/CurrentTime.h>
fpizlo@apple.com5e29b762016-03-18 00:53:24 +000061#include <wtf/MainThread.h>
fpizlo@apple.com74590cb2015-09-29 16:39:24 +000062#include <wtf/ParallelVectorIterator.h>
mhahnenberg@apple.com537512e2014-03-31 23:27:29 +000063#include <wtf/ProcessID.h>
joepeck@webkit.org14c5caf2015-10-12 21:29:21 +000064#include <wtf/RAMSize.h>
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000065#include <wtf/SimpleStats.h>
darind5893602005-08-01 05:02:13 +000066
annulen@yandex.ru855ac992016-04-30 21:21:22 +000067#if USE(FOUNDATION)
ggaren@apple.com8ca83672016-04-21 04:40:18 +000068#if __has_include(<objc/objc-internal.h>)
69#include <objc/objc-internal.h>
70#else
71extern "C" void* objc_autoreleasePoolPush(void);
72extern "C" void objc_autoreleasePoolPop(void *context);
73#endif
annulen@yandex.ru855ac992016-04-30 21:21:22 +000074#endif // USE(FOUNDATION)
ggaren@apple.com8ca83672016-04-21 04:40:18 +000075
ggaren@apple.comf2663492011-02-05 00:20:16 +000076using namespace std;
77
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +000078namespace JSC {
kocienda66a6d362001-08-24 14:24:45 +000079
fpizlo@apple.com74590cb2015-09-29 16:39:24 +000080namespace {
ggaren@apple.com8a23d6a2011-06-09 19:44:37 +000081
ggaren@apple.com9a070932012-05-22 19:17:57 +000082static const size_t largeHeapSize = 32 * MB; // About 1.5X the average webpage.
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000083const size_t smallHeapSize = 1 * MB; // Matches the FastMalloc per-thread cache.
oliver@apple.com3eb80372011-10-12 01:11:04 +000084
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000085size_t minHeapSize(HeapType heapType, size_t ramSize)
fpizlo@apple.comf49ce5c2011-08-02 20:40:17 +000086{
ggaren@apple.com9a070932012-05-22 19:17:57 +000087 if (heapType == LargeHeap)
88 return min(largeHeapSize, ramSize / 4);
fpizlo@apple.comc7b47212011-08-03 23:35:03 +000089 return smallHeapSize;
fpizlo@apple.comf49ce5c2011-08-02 20:40:17 +000090}
ggaren@apple.comf2663492011-02-05 00:20:16 +000091
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000092size_t proportionalHeapSize(size_t heapSize, size_t ramSize)
ggaren@apple.com9a070932012-05-22 19:17:57 +000093{
94 // Try to stay under 1/2 RAM size to leave room for the DOM, rendering, networking, etc.
95 if (heapSize < ramSize / 4)
96 return 2 * heapSize;
97 if (heapSize < ramSize / 2)
98 return 1.5 * heapSize;
99 return 1.25 * heapSize;
100}
101
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000102bool isValidSharedInstanceThreadState(VM* vm)
ggaren@apple.com99cc9d92011-05-26 21:46:09 +0000103{
andersca@apple.comb987aae2013-07-26 00:13:13 +0000104 return vm->currentThreadIsHoldingAPILock();
ggaren@apple.com99cc9d92011-05-26 21:46:09 +0000105}
106
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000107bool isValidThreadState(VM* vm)
ggaren@apple.com99cc9d92011-05-26 21:46:09 +0000108{
barraclough@apple.com0cde90d2014-03-20 21:05:49 +0000109 if (vm->atomicStringTable() != wtfThreadData().atomicStringTable())
ggaren@apple.com99cc9d92011-05-26 21:46:09 +0000110 return false;
111
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000112 if (vm->isSharedInstance() && !isValidSharedInstanceThreadState(vm))
ggaren@apple.com99cc9d92011-05-26 21:46:09 +0000113 return false;
114
115 return true;
116}
117
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000118void recordType(TypeCountSet& set, JSCell* cell)
ggaren@apple.com8a23d6a2011-06-09 19:44:37 +0000119{
fpizlo@apple.comaeddff92016-07-18 21:33:45 +0000120 const char* typeName = "[unknown]";
ggaren@apple.com8a23d6a2011-06-09 19:44:37 +0000121 const ClassInfo* info = cell->classInfo();
fpizlo@apple.comaeddff92016-07-18 21:33:45 +0000122 if (info && info->className)
123 typeName = info->className;
124 set.add(typeName);
ggaren@apple.com8a23d6a2011-06-09 19:44:37 +0000125}
126
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000127bool measurePhaseTiming()
128{
129 return false;
130}
131
132HashMap<const char*, GCTypeMap<SimpleStats>>& timingStats()
133{
134 static HashMap<const char*, GCTypeMap<SimpleStats>>* result;
135 static std::once_flag once;
136 std::call_once(
137 once,
138 [] {
139 result = new HashMap<const char*, GCTypeMap<SimpleStats>>();
140 });
141 return *result;
142}
143
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000144SimpleStats& timingStats(const char* name, CollectionScope scope)
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000145{
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000146 return timingStats().add(name, GCTypeMap<SimpleStats>()).iterator->value[scope];
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000147}
148
149class TimingScope {
150public:
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000151 TimingScope(Optional<CollectionScope> scope, const char* name)
152 : m_scope(scope)
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000153 , m_name(name)
154 {
155 if (measurePhaseTiming())
156 m_before = monotonicallyIncreasingTimeMS();
157 }
158
159 TimingScope(Heap& heap, const char* name)
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000160 : TimingScope(heap.collectionScope(), name)
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000161 {
162 }
163
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000164 void setScope(Optional<CollectionScope> scope)
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000165 {
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000166 m_scope = scope;
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000167 }
168
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000169 void setScope(Heap& heap)
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000170 {
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000171 setScope(heap.collectionScope());
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000172 }
173
174 ~TimingScope()
175 {
176 if (measurePhaseTiming()) {
177 double after = monotonicallyIncreasingTimeMS();
178 double timing = after - m_before;
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000179 SimpleStats& stats = timingStats(m_name, *m_scope);
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000180 stats.add(timing);
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000181 dataLog("[GC:", *m_scope, "] ", m_name, " took: ", timing, " ms (average ", stats.mean(), " ms).\n");
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000182 }
183 }
184private:
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000185 Optional<CollectionScope> m_scope;
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000186 double m_before;
187 const char* m_name;
188};
189
ggaren@apple.com8a23d6a2011-06-09 19:44:37 +0000190} // anonymous namespace
191
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000192Heap::Heap(VM* vm, HeapType heapType)
ggaren@apple.com9a070932012-05-22 19:17:57 +0000193 : m_heapType(heapType)
fpizlo@apple.comdea6d262015-05-08 02:12:35 +0000194 , m_ramSize(Options::forceRAMSize() ? Options::forceRAMSize() : ramSize())
ggaren@apple.com9a070932012-05-22 19:17:57 +0000195 , m_minBytesPerCycle(minHeapSize(m_heapType, m_ramSize))
mhahnenberg@apple.com98daed02012-04-25 01:29:42 +0000196 , m_sizeAfterLastCollect(0)
mhahnenberg@apple.com0d81ace2014-03-20 01:56:19 +0000197 , m_sizeAfterLastFullCollect(0)
198 , m_sizeBeforeLastFullCollect(0)
199 , m_sizeAfterLastEdenCollect(0)
200 , m_sizeBeforeLastEdenCollect(0)
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +0000201 , m_bytesAllocatedThisCycle(0)
mhahnenberg@apple.com0d81ace2014-03-20 01:56:19 +0000202 , m_bytesAbandonedSinceLastFullCollect(0)
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +0000203 , m_maxEdenSize(m_minBytesPerCycle)
204 , m_maxHeapSize(m_minBytesPerCycle)
205 , m_shouldDoFullCollection(false)
mhahnenberg@apple.come2789cf2013-09-09 00:11:57 +0000206 , m_totalBytesVisited(0)
oliver@apple.com44d89542011-09-20 18:31:37 +0000207 , m_objectSpace(this)
ggaren@apple.come2ebb8c2015-03-11 21:29:57 +0000208 , m_extraMemorySize(0)
209 , m_deprecatedExtraMemorySize(0)
mark.lam@apple.com6aba4362015-02-26 19:44:08 +0000210 , m_machineThreads(this)
fpizlo@apple.com42e88d02015-09-23 01:35:49 +0000211 , m_slotVisitor(*this)
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000212 , m_handleSet(vm)
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000213 , m_codeBlocks(std::make_unique<CodeBlockSet>())
214 , m_jitStubRoutines(std::make_unique<JITStubRoutineSet>())
commit-queue@webkit.orgf42601f2011-07-12 22:35:39 +0000215 , m_isSafeToCollect(false)
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +0000216 , m_writeBarrierBuffer(256)
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000217 , m_vm(vm)
mhahnenberg@apple.combce046b2014-03-21 21:53:25 +0000218 // We seed with 10ms so that GCActivityCallback::didAllocate doesn't continuously
219 // schedule the timer if we've never done a collection.
220 , m_lastFullGCLength(0.01)
221 , m_lastEdenGCLength(0.01)
fpizlo@apple.com7ca619d2016-10-25 23:22:48 +0000222#if USE(CF)
223 , m_runLoop(CFRunLoopGetCurrent())
224#endif // USE(CF)
mhahnenberg@apple.com0d81ace2014-03-20 01:56:19 +0000225 , m_fullActivityCallback(GCActivityCallback::createFullTimer(this))
mhahnenberg@apple.com0d81ace2014-03-20 01:56:19 +0000226 , m_edenActivityCallback(GCActivityCallback::createEdenTimer(this))
carlosgc@webkit.org040a9882015-11-26 13:52:45 +0000227 , m_sweeper(std::make_unique<IncrementalSweeper>(this))
oliver@apple.com284cc3d2013-07-25 04:00:33 +0000228 , m_deferralDepth(0)
ggaren@apple.com8ca83672016-04-21 04:40:18 +0000229#if USE(FOUNDATION)
msaboff@apple.com84946d42015-02-06 01:12:00 +0000230 , m_delayedReleaseRecursionCount(0)
231#endif
commit-queue@webkit.org51775072015-09-30 17:17:27 +0000232 , m_helperClient(&heapHelperPool())
ap@webkit.org960c28e2008-06-19 17:29:29 +0000233{
mark.lam@apple.com34e46672014-11-20 23:28:41 +0000234 if (Options::verifyHeap())
235 m_verifier = std::make_unique<HeapVerifier>(this, Options::numberOfGCCyclesToRecordForVerification());
ap@webkit.org960c28e2008-06-19 17:29:29 +0000236}
darin070530c2002-10-07 21:06:29 +0000237
ap@webkit.org0b7e63b2008-06-26 18:59:26 +0000238Heap::~Heap()
239{
akling@apple.com206b96f2015-05-07 18:32:29 +0000240 for (WeakBlock* block : m_logicallyEmptyWeakBlocks)
akling@apple.com43fb3522015-11-01 02:29:47 +0000241 WeakBlock::destroy(*this, block);
darin@apple.comb6295d42008-10-02 23:48:47 +0000242}
243
mhahnenberg@apple.com2e132e42012-05-03 00:14:05 +0000244bool Heap::isPagedOut(double deadline)
245{
fpizlo@apple.comd1725cb2016-09-08 22:12:05 +0000246 return m_objectSpace.isPagedOut(deadline);
mhahnenberg@apple.com2e132e42012-05-03 00:14:05 +0000247}
248
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000249// The VM is being destroyed and the collector will never run again.
ggaren@apple.comc143e902012-04-28 20:51:27 +0000250// Run all pending finalizers now because we won't get another chance.
251void Heap::lastChanceToFinalize()
darin@apple.comb6295d42008-10-02 23:48:47 +0000252{
mark.lam@apple.com30721252013-11-21 05:29:42 +0000253 RELEASE_ASSERT(!m_vm->entryScope);
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000254 RELEASE_ASSERT(!m_collectionScope);
255 RELEASE_ASSERT(m_mutatorState == MutatorState::Running);
ap@webkit.org8672bcf2008-08-11 12:01:26 +0000256
keith_miller@apple.com4697a6c2016-03-23 00:19:47 +0000257 m_arrayBuffers.lastChanceToFinalize();
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000258 m_codeBlocks->lastChanceToFinalize();
ggaren@apple.com96fa0e72012-05-23 20:47:46 +0000259 m_objectSpace.lastChanceToFinalize();
msaboff@apple.com84946d42015-02-06 01:12:00 +0000260 releaseDelayedReleasedObjects();
akling@apple.come92da672015-04-04 23:16:21 +0000261
262 sweepAllLogicallyEmptyWeakBlocks();
msaboff@apple.com84946d42015-02-06 01:12:00 +0000263}
264
265void Heap::releaseDelayedReleasedObjects()
266{
ggaren@apple.com8ca83672016-04-21 04:40:18 +0000267#if USE(FOUNDATION)
msaboff@apple.com847d1cb2015-03-04 05:33:37 +0000268 // We need to guard against the case that releasing an object can create more objects due to the
269 // release calling into JS. When those JS call(s) exit and all locks are being dropped we end up
270 // back here and could try to recursively release objects. We guard that with a recursive entry
271 // count. Only the initial call will release objects, recursive calls simple return and let the
272 // the initial call to the function take care of any objects created during release time.
273 // This also means that we need to loop until there are no objects in m_delayedReleaseObjects
274 // and use a temp Vector for the actual releasing.
msaboff@apple.com84946d42015-02-06 01:12:00 +0000275 if (!m_delayedReleaseRecursionCount++) {
276 while (!m_delayedReleaseObjects.isEmpty()) {
msaboff@apple.com847d1cb2015-03-04 05:33:37 +0000277 ASSERT(m_vm->currentThreadIsHoldingAPILock());
278
aestes@apple.com13aae082016-01-02 08:03:08 +0000279 Vector<RetainPtr<CFTypeRef>> objectsToRelease = WTFMove(m_delayedReleaseObjects);
msaboff@apple.com847d1cb2015-03-04 05:33:37 +0000280
281 {
282 // We need to drop locks before calling out to arbitrary code.
283 JSLock::DropAllLocks dropAllLocks(m_vm);
284
ggaren@apple.com8ca83672016-04-21 04:40:18 +0000285 void* context = objc_autoreleasePoolPush();
msaboff@apple.com847d1cb2015-03-04 05:33:37 +0000286 objectsToRelease.clear();
ggaren@apple.com8ca83672016-04-21 04:40:18 +0000287 objc_autoreleasePoolPop(context);
msaboff@apple.com847d1cb2015-03-04 05:33:37 +0000288 }
msaboff@apple.com84946d42015-02-06 01:12:00 +0000289 }
290 }
291 m_delayedReleaseRecursionCount--;
292#endif
ap@webkit.org0b7e63b2008-06-26 18:59:26 +0000293}
294
ggaren@apple.come2ebb8c2015-03-11 21:29:57 +0000295void Heap::reportExtraMemoryAllocatedSlowCase(size_t size)
mjs06ed4662007-07-25 21:50:00 +0000296{
ggaren@apple.come2ebb8c2015-03-11 21:29:57 +0000297 didAllocate(size);
oliver@apple.com284cc3d2013-07-25 04:00:33 +0000298 collectIfNecessaryOrDefer();
mjs06ed4662007-07-25 21:50:00 +0000299}
300
ggaren@apple.come2ebb8c2015-03-11 21:29:57 +0000301void Heap::deprecatedReportExtraMemorySlowCase(size_t size)
302{
303 m_deprecatedExtraMemorySize += size;
304 reportExtraMemoryAllocatedSlowCase(size);
305}
306
mhahnenberg@apple.com98daed02012-04-25 01:29:42 +0000307void Heap::reportAbandonedObjectGraph()
308{
309 // Our clients don't know exactly how much memory they
310 // are abandoning so we just guess for them.
sbarati@apple.come229c4d2016-07-05 19:49:19 +0000311 size_t abandonedBytes = static_cast<size_t>(0.1 * capacity());
mhahnenberg@apple.com98daed02012-04-25 01:29:42 +0000312
313 // We want to accelerate the next collection. Because memory has just
314 // been abandoned, the next collection has the potential to
315 // be more profitable. Since allocation is the trigger for collection,
316 // we hasten the next collection by pretending that we've allocated more memory.
mhahnenberg@apple.com0d81ace2014-03-20 01:56:19 +0000317 if (m_fullActivityCallback) {
318 m_fullActivityCallback->didAllocate(
319 m_sizeAfterLastCollect - m_sizeAfterLastFullCollect + m_bytesAllocatedThisCycle + m_bytesAbandonedSinceLastFullCollect);
320 }
sbarati@apple.come229c4d2016-07-05 19:49:19 +0000321 m_bytesAbandonedSinceLastFullCollect += abandonedBytes;
mhahnenberg@apple.com98daed02012-04-25 01:29:42 +0000322}
323
ggaren@apple.comdc067b62009-05-01 22:43:39 +0000324void Heap::protect(JSValue k)
mjsc4bb2952005-12-13 11:06:10 +0000325{
mjs9f1f97a2007-03-20 23:57:01 +0000326 ASSERT(k);
andersca@apple.comb987aae2013-07-26 00:13:13 +0000327 ASSERT(m_vm->currentThreadIsHoldingAPILock());
mjsc4bb2952005-12-13 11:06:10 +0000328
weinig@apple.com92fdaef2009-01-20 00:54:18 +0000329 if (!k.isCell())
ap@webkit.org84ea6b92008-06-04 16:29:49 +0000330 return;
mjsc4bb2952005-12-13 11:06:10 +0000331
weinig@apple.com92fdaef2009-01-20 00:54:18 +0000332 m_protectedValues.add(k.asCell());
mjsc4bb2952005-12-13 11:06:10 +0000333}
334
barraclough@apple.com88bb3112010-03-24 07:11:51 +0000335bool Heap::unprotect(JSValue k)
mjsc4bb2952005-12-13 11:06:10 +0000336{
mjs9f1f97a2007-03-20 23:57:01 +0000337 ASSERT(k);
andersca@apple.comb987aae2013-07-26 00:13:13 +0000338 ASSERT(m_vm->currentThreadIsHoldingAPILock());
mjsc4bb2952005-12-13 11:06:10 +0000339
weinig@apple.com92fdaef2009-01-20 00:54:18 +0000340 if (!k.isCell())
barraclough@apple.com88bb3112010-03-24 07:11:51 +0000341 return false;
mjsc4bb2952005-12-13 11:06:10 +0000342
barraclough@apple.com88bb3112010-03-24 07:11:51 +0000343 return m_protectedValues.remove(k.asCell());
mjsc4bb2952005-12-13 11:06:10 +0000344}
345
fpizlo@apple.com0e0d9312013-08-15 20:43:06 +0000346void Heap::addReference(JSCell* cell, ArrayBuffer* buffer)
347{
348 if (m_arrayBuffers.addReference(cell, buffer)) {
349 collectIfNecessaryOrDefer();
350 didAllocate(buffer->gcSizeEstimateInBytes());
351 }
352}
353
fpizlo@apple.comd13163d2011-09-03 05:14:04 +0000354void Heap::harvestWeakReferences()
355{
356 m_slotVisitor.harvestWeakReferences();
357}
358
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +0000359void Heap::finalizeUnconditionalFinalizers()
360{
361 m_slotVisitor.finalizeUnconditionalFinalizers();
362}
363
mhahnenberg@apple.combee96a32013-09-16 19:48:48 +0000364void Heap::willStartIterating()
mark.lam@apple.comd4eb0d32013-04-17 16:32:44 +0000365{
mhahnenberg@apple.combee96a32013-09-16 19:48:48 +0000366 m_objectSpace.willStartIterating();
367}
368
369void Heap::didFinishIterating()
370{
371 m_objectSpace.didFinishIterating();
mark.lam@apple.comd4eb0d32013-04-17 16:32:44 +0000372}
373
fpizlo@apple.com46050f72016-06-17 04:48:47 +0000374void Heap::completeAllJITPlans()
fpizlo@apple.com8e470a22015-09-21 20:10:04 +0000375{
fpizlo@apple.com46050f72016-06-17 04:48:47 +0000376#if ENABLE(JIT)
377 JITWorklist::instance()->completeAllForVM(*m_vm);
378#endif // ENABLE(JIT)
fpizlo@apple.com8e470a22015-09-21 20:10:04 +0000379#if ENABLE(DFG_JIT)
380 DFG::completeAllPlansForVM(*m_vm);
381#endif
382}
383
akling@apple.com09cd9c02015-03-05 02:19:14 +0000384void Heap::markRoots(double gcStartTime, void* stackOrigin, void* stackTop, MachineThreads::RegisterState& calleeSavedRegisters)
kocienda66a6d362001-08-24 14:24:45 +0000385{
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000386 TimingScope markRootsTimingScope(*this, "Heap::markRoots");
387
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000388 ASSERT(isValidThreadState(m_vm));
ap@webkit.org01aff702008-08-20 07:23:06 +0000389
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000390 HeapRootVisitor heapRootVisitor(m_slotVisitor);
391
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000392 {
393 TimingScope preConvergenceTimingScope(*this, "Heap::markRoots before convergence");
msaboff@apple.com95894332014-01-29 19:18:54 +0000394
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000395#if ENABLE(DFG_JIT)
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000396 DFG::rememberCodeBlocks(*m_vm);
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000397#endif
commit-queue@webkit.org0263ad32015-10-06 05:51:34 +0000398
sbarati@apple.coma4ce86b2016-01-11 06:49:49 +0000399#if ENABLE(SAMPLING_PROFILER)
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000400 if (SamplingProfiler* samplingProfiler = m_vm->samplingProfiler()) {
401 // Note that we need to own the lock from now until we're done
402 // marking the SamplingProfiler's data because once we verify the
403 // SamplingProfiler's stack traces, we don't want it to accumulate
404 // more stack traces before we get the chance to mark it.
405 // This lock is released inside visitSamplingProfiler().
406 samplingProfiler->getLock().lock();
407 samplingProfiler->processUnverifiedStackTraces();
408 }
sbarati@apple.coma4ce86b2016-01-11 06:49:49 +0000409#endif // ENABLE(SAMPLING_PROFILER)
410
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000411 if (m_collectionScope == CollectionScope::Full) {
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000412 m_opaqueRoots.clear();
413 m_slotVisitor.clearMarkStack();
414 }
415
fpizlo@apple.com71bb6d22016-09-13 04:33:19 +0000416 beginMarking();
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000417
418 m_parallelMarkersShouldExit = false;
419
420 m_helperClient.setFunction(
421 [this] () {
422 SlotVisitor* slotVisitor;
423 {
424 LockHolder locker(m_parallelSlotVisitorLock);
425 if (m_availableParallelSlotVisitors.isEmpty()) {
426 std::unique_ptr<SlotVisitor> newVisitor =
427 std::make_unique<SlotVisitor>(*this);
428 slotVisitor = newVisitor.get();
429 m_parallelSlotVisitors.append(WTFMove(newVisitor));
430 } else
431 slotVisitor = m_availableParallelSlotVisitors.takeLast();
432 }
433
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000434 WTF::registerGCThread(GCThreadType::Helper);
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000435
436 {
437 ParallelModeEnabler parallelModeEnabler(*slotVisitor);
438 slotVisitor->didStartMarking();
439 slotVisitor->drainFromShared(SlotVisitor::SlaveDrain);
440 }
441
442 {
443 LockHolder locker(m_parallelSlotVisitorLock);
444 m_availableParallelSlotVisitors.append(slotVisitor);
445 }
446 });
447
448 m_slotVisitor.didStartMarking();
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000449 }
fpizlo@apple.com5f866062015-09-26 18:07:09 +0000450
oliver@apple.com73792612011-10-12 00:24:12 +0000451 {
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000452 SuperSamplerScope superSamplerScope(false);
453 TimingScope convergenceTimingScope(*this, "Heap::markRoots convergence");
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000454 ParallelModeEnabler enabler(m_slotVisitor);
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000455
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000456 m_slotVisitor.donateAndDrain();
fpizlo@apple.com7b231642016-10-11 23:52:02 +0000457
458 {
459 TimingScope preConvergenceTimingScope(*this, "Heap::markRoots conservative scan");
460 ConservativeRoots conservativeRoots(*this);
461 SuperSamplerScope superSamplerScope(false);
462 gatherStackRoots(conservativeRoots, stackOrigin, stackTop, calleeSavedRegisters);
463 gatherJSStackRoots(conservativeRoots);
464 gatherScratchBufferRoots(conservativeRoots);
465 visitConservativeRoots(conservativeRoots);
466
467 // We want to do this to conservatively ensure that we rescan any code blocks that are
468 // running right now. However, we need to be sure to do it *after* we mark the code block
469 // so that we know for sure if it really needs a barrier.
470 m_codeBlocks->writeBarrierCurrentlyExecuting(this);
471 }
472
mhahnenberg@apple.com1629c062014-04-15 21:05:09 +0000473 visitExternalRememberedSet();
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000474 visitSmallStrings();
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000475 visitProtectedObjects(heapRootVisitor);
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000476 visitArgumentBuffers(heapRootVisitor);
477 visitException(heapRootVisitor);
478 visitStrongHandles(heapRootVisitor);
479 visitHandleStack(heapRootVisitor);
sbarati@apple.coma4ce86b2016-01-11 06:49:49 +0000480 visitSamplingProfiler();
fpizlo@apple.com39303e02016-04-05 22:17:35 +0000481 visitShadowChicken();
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000482 traceCodeBlocksAndJITStubRoutines();
fpizlo@apple.com71bb6d22016-09-13 04:33:19 +0000483 m_slotVisitor.drainFromShared(SlotVisitor::MasterDrain);
oliver@apple.com32b720a2011-10-05 19:07:18 +0000484 }
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000485
486 TimingScope postConvergenceTimingScope(*this, "Heap::markRoots after convergence");
ggaren@apple.com6d8758c2011-04-14 23:20:25 +0000487
ggaren@apple.com76215812012-04-04 05:28:13 +0000488 // Weak references must be marked last because their liveness depends on
489 // the liveness of the rest of the object graph.
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000490 visitWeakHandles(heapRootVisitor);
ggaren@apple.com76215812012-04-04 05:28:13 +0000491
fpizlo@apple.com42e88d02015-09-23 01:35:49 +0000492 {
493 std::lock_guard<Lock> lock(m_markingMutex);
494 m_parallelMarkersShouldExit = true;
495 m_markingConditionVariable.notifyAll();
496 }
commit-queue@webkit.org51775072015-09-30 17:17:27 +0000497 m_helperClient.finish();
mhahnenberg@apple.com040ef242014-04-05 20:05:04 +0000498 updateObjectCounts(gcStartTime);
fpizlo@apple.com71bb6d22016-09-13 04:33:19 +0000499 endMarking();
mhahnenberg@apple.com02e39c72012-10-12 19:38:35 +0000500}
501
akling@apple.com09cd9c02015-03-05 02:19:14 +0000502void Heap::gatherStackRoots(ConservativeRoots& roots, void* stackOrigin, void* stackTop, MachineThreads::RegisterState& calleeSavedRegisters)
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000503{
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000504 m_jitStubRoutines->clearMarks();
505 m_machineThreads.gatherConservativeRoots(roots, *m_jitStubRoutines, *m_codeBlocks, stackOrigin, stackTop, calleeSavedRegisters);
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000506}
507
508void Heap::gatherJSStackRoots(ConservativeRoots& roots)
509{
dbatyai.u-szeged@partner.samsung.com46f07e52014-06-19 16:32:31 +0000510#if !ENABLE(JIT)
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000511 m_vm->interpreter->cloopStack().gatherConservativeRoots(roots, *m_jitStubRoutines, *m_codeBlocks);
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000512#else
513 UNUSED_PARAM(roots);
514#endif
515}
516
517void Heap::gatherScratchBufferRoots(ConservativeRoots& roots)
518{
519#if ENABLE(DFG_JIT)
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000520 m_vm->gatherConservativeRoots(roots);
521#else
522 UNUSED_PARAM(roots);
523#endif
524}
525
fpizlo@apple.com71bb6d22016-09-13 04:33:19 +0000526void Heap::beginMarking()
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000527{
fpizlo@apple.com71bb6d22016-09-13 04:33:19 +0000528 TimingScope timingScope(*this, "Heap::beginMarking");
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000529 if (m_collectionScope == CollectionScope::Full)
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000530 m_codeBlocks->clearMarksForFullCollection();
531
532 {
fpizlo@apple.com96352992016-09-20 18:12:18 +0000533 TimingScope clearMarksTimingScope(*this, "m_objectSpace.beginMarking");
534 m_objectSpace.beginMarking();
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000535 }
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000536}
537
mhahnenberg@apple.com1629c062014-04-15 21:05:09 +0000538void Heap::visitExternalRememberedSet()
539{
540#if JSC_OBJC_API_ENABLED
541 scanExternalRememberedSet(*m_vm, m_slotVisitor);
542#endif
543}
544
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000545void Heap::visitSmallStrings()
546{
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000547 if (!m_vm->smallStrings.needsToBeVisited(*m_collectionScope))
mhahnenb@gmail.com38687762015-01-23 07:04:05 +0000548 return;
mhahnenberg@apple.com040ef242014-04-05 20:05:04 +0000549
mhahnenb@gmail.com38687762015-01-23 07:04:05 +0000550 m_vm->smallStrings.visitStrongReferences(m_slotVisitor);
mhahnenberg@apple.com040ef242014-04-05 20:05:04 +0000551 if (Options::logGC() == GCLogging::Verbose)
552 dataLog("Small strings:\n", m_slotVisitor);
mhahnenberg@apple.com040ef242014-04-05 20:05:04 +0000553 m_slotVisitor.donateAndDrain();
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000554}
555
556void Heap::visitConservativeRoots(ConservativeRoots& roots)
557{
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000558 m_slotVisitor.append(roots);
mhahnenberg@apple.com040ef242014-04-05 20:05:04 +0000559
560 if (Options::logGC() == GCLogging::Verbose)
561 dataLog("Conservative Roots:\n", m_slotVisitor);
562
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000563 m_slotVisitor.donateAndDrain();
564}
565
fpizlo@apple.com04a048c2014-04-28 19:01:07 +0000566void Heap::visitCompilerWorklistWeakReferences()
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000567{
568#if ENABLE(DFG_JIT)
mark.lam@apple.coma9060542014-04-24 00:43:15 +0000569 for (auto worklist : m_suspendedCompilerWorklists)
ggaren@apple.com51be9a22015-09-09 22:00:58 +0000570 worklist->visitWeakReferences(m_slotVisitor);
mhahnenberg@apple.com040ef242014-04-05 20:05:04 +0000571
572 if (Options::logGC() == GCLogging::Verbose)
573 dataLog("DFG Worklists:\n", m_slotVisitor);
fpizlo@apple.com04a048c2014-04-28 19:01:07 +0000574#endif
575}
mhahnenberg@apple.com040ef242014-04-05 20:05:04 +0000576
fpizlo@apple.com04a048c2014-04-28 19:01:07 +0000577void Heap::removeDeadCompilerWorklistEntries()
578{
579#if ENABLE(DFG_JIT)
fpizlo@apple.com04a048c2014-04-28 19:01:07 +0000580 for (auto worklist : m_suspendedCompilerWorklists)
581 worklist->removeDeadPlans(*m_vm);
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000582#endif
583}
584
commit-queue@webkit.orgd38d0682016-03-03 05:15:56 +0000585bool Heap::isHeapSnapshotting() const
586{
587 HeapProfiler* heapProfiler = m_vm->heapProfiler();
588 if (UNLIKELY(heapProfiler))
589 return heapProfiler->activeSnapshotBuilder();
590 return false;
591}
592
commit-queue@webkit.orgc4c0f562016-03-07 23:45:38 +0000593struct GatherHeapSnapshotData : MarkedBlock::CountFunctor {
594 GatherHeapSnapshotData(HeapSnapshotBuilder& builder)
595 : m_builder(builder)
596 {
597 }
598
fpizlo@apple.comaeddff92016-07-18 21:33:45 +0000599 IterationStatus operator()(HeapCell* heapCell, HeapCell::Kind kind) const
commit-queue@webkit.orgc4c0f562016-03-07 23:45:38 +0000600 {
fpizlo@apple.comaeddff92016-07-18 21:33:45 +0000601 if (kind == HeapCell::JSCell) {
602 JSCell* cell = static_cast<JSCell*>(heapCell);
603 cell->methodTable()->heapSnapshot(cell, m_builder);
604 }
commit-queue@webkit.orgc4c0f562016-03-07 23:45:38 +0000605 return IterationStatus::Continue;
606 }
607
608 HeapSnapshotBuilder& m_builder;
609};
610
611void Heap::gatherExtraHeapSnapshotData(HeapProfiler& heapProfiler)
612{
commit-queue@webkit.orgc4c0f562016-03-07 23:45:38 +0000613 if (HeapSnapshotBuilder* builder = heapProfiler.activeSnapshotBuilder()) {
614 HeapIterationScope heapIterationScope(*this);
615 GatherHeapSnapshotData functor(*builder);
616 m_objectSpace.forEachLiveCell(heapIterationScope, functor);
617 }
618}
619
commit-queue@webkit.orgd38d0682016-03-03 05:15:56 +0000620struct RemoveDeadHeapSnapshotNodes : MarkedBlock::CountFunctor {
621 RemoveDeadHeapSnapshotNodes(HeapSnapshot& snapshot)
622 : m_snapshot(snapshot)
623 {
624 }
625
fpizlo@apple.comaeddff92016-07-18 21:33:45 +0000626 IterationStatus operator()(HeapCell* cell, HeapCell::Kind kind) const
commit-queue@webkit.orgd38d0682016-03-03 05:15:56 +0000627 {
fpizlo@apple.comaeddff92016-07-18 21:33:45 +0000628 if (kind == HeapCell::JSCell)
629 m_snapshot.sweepCell(static_cast<JSCell*>(cell));
commit-queue@webkit.orgd38d0682016-03-03 05:15:56 +0000630 return IterationStatus::Continue;
631 }
632
633 HeapSnapshot& m_snapshot;
634};
635
commit-queue@webkit.orgc4c0f562016-03-07 23:45:38 +0000636void Heap::removeDeadHeapSnapshotNodes(HeapProfiler& heapProfiler)
commit-queue@webkit.orgd38d0682016-03-03 05:15:56 +0000637{
commit-queue@webkit.orgc4c0f562016-03-07 23:45:38 +0000638 if (HeapSnapshot* snapshot = heapProfiler.mostRecentSnapshot()) {
639 HeapIterationScope heapIterationScope(*this);
640 RemoveDeadHeapSnapshotNodes functor(*snapshot);
641 m_objectSpace.forEachDeadCell(heapIterationScope, functor);
642 snapshot->shrinkToFit();
commit-queue@webkit.orgd38d0682016-03-03 05:15:56 +0000643 }
644}
645
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000646void Heap::visitProtectedObjects(HeapRootVisitor& heapRootVisitor)
647{
andersca@apple.comcca6e6d2014-03-05 18:59:58 +0000648 for (auto& pair : m_protectedValues)
mhahnenberg@apple.comb5b2edc2014-03-05 16:46:23 +0000649 heapRootVisitor.visit(&pair.key);
mhahnenberg@apple.com040ef242014-04-05 20:05:04 +0000650
651 if (Options::logGC() == GCLogging::Verbose)
652 dataLog("Protected Objects:\n", m_slotVisitor);
653
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000654 m_slotVisitor.donateAndDrain();
655}
656
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000657void Heap::visitArgumentBuffers(HeapRootVisitor& visitor)
658{
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000659 if (!m_markListSet || !m_markListSet->size())
660 return;
661
662 MarkedArgumentBuffer::markLists(visitor, *m_markListSet);
mhahnenberg@apple.com040ef242014-04-05 20:05:04 +0000663
664 if (Options::logGC() == GCLogging::Verbose)
665 dataLog("Argument Buffers:\n", m_slotVisitor);
666
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000667 m_slotVisitor.donateAndDrain();
668}
669
670void Heap::visitException(HeapRootVisitor& visitor)
671{
mark.lam@apple.comb7a67372015-06-12 05:39:28 +0000672 if (!m_vm->exception() && !m_vm->lastException())
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000673 return;
674
675 visitor.visit(m_vm->addressOfException());
mark.lam@apple.comb7a67372015-06-12 05:39:28 +0000676 visitor.visit(m_vm->addressOfLastException());
mhahnenberg@apple.com040ef242014-04-05 20:05:04 +0000677
678 if (Options::logGC() == GCLogging::Verbose)
679 dataLog("Exceptions:\n", m_slotVisitor);
680
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000681 m_slotVisitor.donateAndDrain();
682}
683
684void Heap::visitStrongHandles(HeapRootVisitor& visitor)
685{
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000686 m_handleSet.visitStrongHandles(visitor);
mhahnenberg@apple.com040ef242014-04-05 20:05:04 +0000687
688 if (Options::logGC() == GCLogging::Verbose)
689 dataLog("Strong Handles:\n", m_slotVisitor);
690
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000691 m_slotVisitor.donateAndDrain();
692}
693
694void Heap::visitHandleStack(HeapRootVisitor& visitor)
695{
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000696 m_handleStack.visit(visitor);
mhahnenberg@apple.com040ef242014-04-05 20:05:04 +0000697
698 if (Options::logGC() == GCLogging::Verbose)
699 dataLog("Handle Stack:\n", m_slotVisitor);
700
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000701 m_slotVisitor.donateAndDrain();
702}
703
sbarati@apple.coma4ce86b2016-01-11 06:49:49 +0000704void Heap::visitSamplingProfiler()
705{
706#if ENABLE(SAMPLING_PROFILER)
707 if (SamplingProfiler* samplingProfiler = m_vm->samplingProfiler()) {
708 ASSERT(samplingProfiler->getLock().isLocked());
sbarati@apple.coma4ce86b2016-01-11 06:49:49 +0000709 samplingProfiler->visit(m_slotVisitor);
710 if (Options::logGC() == GCLogging::Verbose)
711 dataLog("Sampling Profiler data:\n", m_slotVisitor);
712
713 m_slotVisitor.donateAndDrain();
714 samplingProfiler->getLock().unlock();
715 }
716#endif // ENABLE(SAMPLING_PROFILER)
717}
718
fpizlo@apple.com39303e02016-04-05 22:17:35 +0000719void Heap::visitShadowChicken()
720{
721 m_vm->shadowChicken().visitChildren(m_slotVisitor);
722}
723
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000724void Heap::traceCodeBlocksAndJITStubRoutines()
725{
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000726 m_jitStubRoutines->traceMarkedStubRoutines(m_slotVisitor);
mhahnenberg@apple.com040ef242014-04-05 20:05:04 +0000727
728 if (Options::logGC() == GCLogging::Verbose)
729 dataLog("Code Blocks and JIT Stub Routines:\n", m_slotVisitor);
730
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000731 m_slotVisitor.donateAndDrain();
732}
733
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000734void Heap::visitWeakHandles(HeapRootVisitor& visitor)
735{
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000736 TimingScope timingScope(*this, "Heap::visitWeakHandles");
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000737 while (true) {
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000738 {
739 TimingScope timingScope(*this, "m_objectSpace.visitWeakSets");
740 m_objectSpace.visitWeakSets(visitor);
741 }
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000742 harvestWeakReferences();
fpizlo@apple.com04a048c2014-04-28 19:01:07 +0000743 visitCompilerWorklistWeakReferences();
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000744 if (m_slotVisitor.isEmpty())
745 break;
mhahnenberg@apple.com040ef242014-04-05 20:05:04 +0000746
747 if (Options::logGC() == GCLogging::Verbose)
748 dataLog("Live Weak Handles:\n", m_slotVisitor);
749
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000750 {
751 ParallelModeEnabler enabler(m_slotVisitor);
752 m_slotVisitor.donateAndDrain();
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000753 m_slotVisitor.drainFromShared(SlotVisitor::MasterDrain);
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000754 }
755 }
756}
757
mhahnenberg@apple.com040ef242014-04-05 20:05:04 +0000758void Heap::updateObjectCounts(double gcStartTime)
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000759{
mhahnenberg@apple.com040ef242014-04-05 20:05:04 +0000760 if (Options::logGC() == GCLogging::Verbose) {
761 size_t visitCount = m_slotVisitor.visitCount();
fpizlo@apple.com42e88d02015-09-23 01:35:49 +0000762 visitCount += threadVisitCount();
ossy@webkit.org2bf2cbb2014-04-06 22:12:09 +0000763 dataLogF("\nNumber of live Objects after GC %lu, took %.6f secs\n", static_cast<unsigned long>(visitCount), WTF::monotonicallyIncreasingTime() - gcStartTime);
mhahnenberg@apple.com040ef242014-04-05 20:05:04 +0000764 }
fpizlo@apple.comdea6d262015-05-08 02:12:35 +0000765
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000766 if (m_collectionScope == CollectionScope::Full)
fpizlo@apple.comdea6d262015-05-08 02:12:35 +0000767 m_totalBytesVisited = 0;
fpizlo@apple.comed5fc472015-10-17 20:27:43 +0000768
769 m_totalBytesVisitedThisCycle = m_slotVisitor.bytesVisited() + threadBytesVisited();
fpizlo@apple.comdea6d262015-05-08 02:12:35 +0000770
fpizlo@apple.comed5fc472015-10-17 20:27:43 +0000771 m_totalBytesVisited += m_totalBytesVisitedThisCycle;
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000772}
773
fpizlo@apple.com71bb6d22016-09-13 04:33:19 +0000774void Heap::endMarking()
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000775{
776 m_slotVisitor.reset();
fpizlo@apple.com42e88d02015-09-23 01:35:49 +0000777
fpizlo@apple.com5f866062015-09-26 18:07:09 +0000778 for (auto& parallelVisitor : m_parallelSlotVisitors)
779 parallelVisitor->reset();
fpizlo@apple.com42e88d02015-09-23 01:35:49 +0000780
781 ASSERT(m_sharedMarkStack.isEmpty());
782 m_weakReferenceHarvesters.removeAll();
fpizlo@apple.com71bb6d22016-09-13 04:33:19 +0000783
fpizlo@apple.com96352992016-09-20 18:12:18 +0000784 m_objectSpace.endMarking();
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +0000785}
786
ggaren@apple.com8a23d6a2011-06-09 19:44:37 +0000787size_t Heap::objectCount()
mjs6d32b072002-11-20 09:34:02 +0000788{
ggaren@apple.com041d0a22012-05-18 00:40:30 +0000789 return m_objectSpace.objectCount();
mjs6d32b072002-11-20 09:34:02 +0000790}
791
ggaren@apple.come2ebb8c2015-03-11 21:29:57 +0000792size_t Heap::extraMemorySize()
fpizlo@apple.com0e0d9312013-08-15 20:43:06 +0000793{
ggaren@apple.come2ebb8c2015-03-11 21:29:57 +0000794 return m_extraMemorySize + m_deprecatedExtraMemorySize + m_arrayBuffers.size();
fpizlo@apple.com0e0d9312013-08-15 20:43:06 +0000795}
796
ggaren@apple.com8a23d6a2011-06-09 19:44:37 +0000797size_t Heap::size()
eric@webkit.org30dc2a32010-05-15 08:46:23 +0000798{
fpizlo@apple.comd1725cb2016-09-08 22:12:05 +0000799 return m_objectSpace.size() + extraMemorySize();
eric@webkit.org30dc2a32010-05-15 08:46:23 +0000800}
801
ggaren@apple.com8a23d6a2011-06-09 19:44:37 +0000802size_t Heap::capacity()
ggaren@apple.com07050262011-01-30 03:32:52 +0000803{
fpizlo@apple.comd1725cb2016-09-08 22:12:05 +0000804 return m_objectSpace.capacity() + extraMemorySize();
darin52b49432002-05-09 00:11:06 +0000805}
806
ap@webkit.org960c28e2008-06-19 17:29:29 +0000807size_t Heap::protectedGlobalObjectCount()
ggaren@apple.com6e4309e2008-01-11 09:52:27 +0000808{
fpizlo@apple.comaeddff92016-07-18 21:33:45 +0000809 size_t result = 0;
810 forEachProtectedCell(
811 [&] (JSCell* cell) {
812 if (cell->isObject() && asObject(cell)->isGlobalObject())
813 result++;
814 });
815 return result;
ggaren@apple.com8a23d6a2011-06-09 19:44:37 +0000816}
ggaren@apple.com79ab2a92011-02-02 05:05:55 +0000817
ggaren@apple.com8a23d6a2011-06-09 19:44:37 +0000818size_t Heap::globalObjectCount()
819{
mhahnenberg@apple.combee96a32013-09-16 19:48:48 +0000820 HeapIterationScope iterationScope(*this);
fpizlo@apple.comaeddff92016-07-18 21:33:45 +0000821 size_t result = 0;
822 m_objectSpace.forEachLiveCell(
823 iterationScope,
824 [&] (HeapCell* heapCell, HeapCell::Kind kind) -> IterationStatus {
825 if (kind != HeapCell::JSCell)
826 return IterationStatus::Continue;
827 JSCell* cell = static_cast<JSCell*>(heapCell);
828 if (cell->isObject() && asObject(cell)->isGlobalObject())
829 result++;
830 return IterationStatus::Continue;
831 });
832 return result;
ggaren@apple.com6e4309e2008-01-11 09:52:27 +0000833}
834
ap@webkit.org960c28e2008-06-19 17:29:29 +0000835size_t Heap::protectedObjectCount()
darin52b49432002-05-09 00:11:06 +0000836{
fpizlo@apple.comaeddff92016-07-18 21:33:45 +0000837 size_t result = 0;
838 forEachProtectedCell(
839 [&] (JSCell*) {
840 result++;
841 });
842 return result;
ggaren@apple.comb843ba82011-02-11 23:31:04 +0000843}
844
gyuyoung.kim@samsung.com221dd0b2014-11-01 00:26:36 +0000845std::unique_ptr<TypeCountSet> Heap::protectedObjectTypeCounts()
ggaren@apple.comb843ba82011-02-11 23:31:04 +0000846{
fpizlo@apple.comaeddff92016-07-18 21:33:45 +0000847 std::unique_ptr<TypeCountSet> result = std::make_unique<TypeCountSet>();
848 forEachProtectedCell(
849 [&] (JSCell* cell) {
850 recordType(*result, cell);
851 });
852 return result;
oliver@apple.combf9b7f82011-04-14 20:17:11 +0000853}
854
gyuyoung.kim@samsung.com221dd0b2014-11-01 00:26:36 +0000855std::unique_ptr<TypeCountSet> Heap::objectTypeCounts()
ggaren@apple.com0fabb552010-02-11 21:28:52 +0000856{
fpizlo@apple.comaeddff92016-07-18 21:33:45 +0000857 std::unique_ptr<TypeCountSet> result = std::make_unique<TypeCountSet>();
mhahnenberg@apple.combee96a32013-09-16 19:48:48 +0000858 HeapIterationScope iterationScope(*this);
fpizlo@apple.comaeddff92016-07-18 21:33:45 +0000859 m_objectSpace.forEachLiveCell(
860 iterationScope,
861 [&] (HeapCell* cell, HeapCell::Kind kind) -> IterationStatus {
862 if (kind == HeapCell::JSCell)
863 recordType(*result, static_cast<JSCell*>(cell));
864 return IterationStatus::Continue;
865 });
866 return result;
ggaren@apple.com0fabb552010-02-11 21:28:52 +0000867}
868
ggaren@apple.com5dd393e2015-08-24 21:43:13 +0000869void Heap::deleteAllCodeBlocks()
mhahnenberg@apple.comcab47522012-03-30 00:36:37 +0000870{
ggaren@apple.comdc5f4262015-09-17 00:16:35 +0000871 // If JavaScript is running, it's not safe to delete all JavaScript code, since
ggaren@apple.com05627c52015-08-13 20:17:02 +0000872 // we'll end up returning to deleted code.
ggaren@apple.comdc5f4262015-09-17 00:16:35 +0000873 RELEASE_ASSERT(!m_vm->entryScope);
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000874 ASSERT(!m_collectionScope);
ggaren@apple.comdc5f4262015-09-17 00:16:35 +0000875
fpizlo@apple.com46050f72016-06-17 04:48:47 +0000876 completeAllJITPlans();
msaboff@apple.com03e811f2012-04-06 16:09:22 +0000877
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000878 for (ExecutableBase* executable : m_executables)
879 executable->clearCode();
ggaren@apple.comd7147572012-06-08 18:17:16 +0000880}
881
ggaren@apple.com5dd393e2015-08-24 21:43:13 +0000882void Heap::deleteAllUnlinkedCodeBlocks()
commit-queue@webkit.orgc656b3d2015-08-20 21:09:19 +0000883{
ggaren@apple.com5dd393e2015-08-24 21:43:13 +0000884 for (ExecutableBase* current : m_executables) {
commit-queue@webkit.orgc656b3d2015-08-20 21:09:19 +0000885 if (!current->isFunctionExecutable())
886 continue;
ggaren@apple.com5dd393e2015-08-24 21:43:13 +0000887 static_cast<FunctionExecutable*>(current)->unlinkedExecutable()->clearCode();
commit-queue@webkit.orgc656b3d2015-08-20 21:09:19 +0000888 }
889}
890
mhahnenberg@apple.com7d223bb2014-04-02 23:50:25 +0000891void Heap::clearUnmarkedExecutables()
ggaren@apple.comd7147572012-06-08 18:17:16 +0000892{
ggaren@apple.com5dd393e2015-08-24 21:43:13 +0000893 for (unsigned i = m_executables.size(); i--;) {
894 ExecutableBase* current = m_executables[i];
ggaren@apple.comd7147572012-06-08 18:17:16 +0000895 if (isMarked(current))
896 continue;
897
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000898 // Eagerly dereference the Executable's JITCode in order to run watchpoint
899 // destructors. Otherwise, watchpoints might fire for deleted CodeBlocks.
900 current->clearCode();
ggaren@apple.com5dd393e2015-08-24 21:43:13 +0000901 std::swap(m_executables[i], m_executables.last());
902 m_executables.removeLast();
ggaren@apple.comd7147572012-06-08 18:17:16 +0000903 }
akling@apple.comb5494572016-01-30 20:48:11 +0000904
905 m_executables.shrinkToFit();
mhahnenberg@apple.com7d223bb2014-04-02 23:50:25 +0000906}
ggaren@apple.comd7147572012-06-08 18:17:16 +0000907
mhahnenberg@apple.com7d223bb2014-04-02 23:50:25 +0000908void Heap::deleteUnmarkedCompiledCode()
909{
mhahnenberg@apple.com7d223bb2014-04-02 23:50:25 +0000910 clearUnmarkedExecutables();
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000911 m_codeBlocks->deleteUnmarkedAndUnreferenced(*m_collectionScope);
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000912 m_jitStubRoutines->deleteUnmarkedJettisonedStubRoutines();
mhahnenberg@apple.comcab47522012-03-30 00:36:37 +0000913}
914
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +0000915void Heap::addToRememberedSet(const JSCell* cell)
916{
917 ASSERT(cell);
mark.lam@apple.comee3c4102015-10-14 18:57:07 +0000918 ASSERT(!Options::useConcurrentJIT() || !isCompilationThread());
fpizlo@apple.com261fc222016-10-12 23:56:34 +0000919 ASSERT(cell->cellState() == CellState::AnthraciteOrBlack);
fpizlo@apple.com3cb36ea2015-10-05 19:35:32 +0000920 // Indicate that this object is grey and that it's one of the following:
921 // - A re-greyed object during a concurrent collection.
922 // - An old remembered object.
923 // "OldGrey" doesn't tell us which of these things is true, but we usually treat the two cases the
924 // same.
925 cell->setCellState(CellState::OldGrey);
ggaren@apple.comc00601e2015-10-05 17:22:20 +0000926 m_slotVisitor.appendToMarkStack(const_cast<JSCell*>(cell));
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +0000927}
928
mark.lam@apple.com38ef9542016-08-11 21:18:14 +0000929void Heap::collectAllGarbage()
ggaren@apple.com9f980342008-10-15 23:33:07 +0000930{
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000931 SuperSamplerScope superSamplerScope(false);
commit-queue@webkit.orgf42601f2011-07-12 22:35:39 +0000932 if (!m_isSafeToCollect)
933 return;
mhahnenberg@apple.com5bc6cc32014-01-07 17:39:52 +0000934
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000935 collectWithoutAnySweep(CollectionScope::Full);
mhahnenberg@apple.com5bc6cc32014-01-07 17:39:52 +0000936
ggaren@apple.coma1cb3762015-03-13 20:14:39 +0000937 DeferGCForAWhile deferGC(*this);
mark.lam@apple.com767e4252016-08-17 00:18:43 +0000938 if (UNLIKELY(Options::useImmortalObjects()))
939 sweeper()->willFinishSweeping();
940 else {
fpizlo@apple.com96352992016-09-20 18:12:18 +0000941 double before = 0;
942 if (Options::logGC()) {
943 dataLog("[Full sweep: ", capacity() / 1024, " kb ");
944 before = currentTimeMS();
945 }
mark.lam@apple.com767e4252016-08-17 00:18:43 +0000946 m_objectSpace.sweep();
947 m_objectSpace.shrink();
fpizlo@apple.com96352992016-09-20 18:12:18 +0000948 if (Options::logGC()) {
949 double after = currentTimeMS();
950 dataLog("=> ", capacity() / 1024, " kb, ", after - before, " ms]\n");
951 }
mark.lam@apple.com767e4252016-08-17 00:18:43 +0000952 }
fpizlo@apple.com96352992016-09-20 18:12:18 +0000953 m_objectSpace.assertNoUnswept();
akling@apple.come92da672015-04-04 23:16:21 +0000954
955 sweepAllLogicallyEmptyWeakBlocks();
ggaren@apple.com7ddf61b2011-01-30 23:07:11 +0000956}
957
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000958void Heap::collect(Optional<CollectionScope> scope)
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000959{
960 SuperSamplerScope superSamplerScope(false);
961 if (!m_isSafeToCollect)
962 return;
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000963
964 collectWithoutAnySweep(scope);
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000965}
966
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000967NEVER_INLINE void Heap::collectWithoutAnySweep(Optional<CollectionScope> scope)
akling@apple.com09cd9c02015-03-05 02:19:14 +0000968{
969 void* stackTop;
970 ALLOCATE_AND_GET_REGISTER_STATE(registers);
971
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000972 collectImpl(scope, wtfThreadData().stack().origin(), &stackTop, registers);
akling@apple.com09cd9c02015-03-05 02:19:14 +0000973
974 sanitizeStackForVM(m_vm);
975}
976
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000977NEVER_INLINE void Heap::collectImpl(Optional<CollectionScope> scope, void* stackOrigin, void* stackTop, MachineThreads::RegisterState& calleeSavedRegisters)
ggaren@apple.com7ddf61b2011-01-30 23:07:11 +0000978{
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000979 SuperSamplerScope superSamplerScope(false);
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000980 TimingScope collectImplTimingScope(scope, "Heap::collectImpl");
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000981
oliver@apple.coma03796a2013-07-25 04:01:20 +0000982#if ENABLE(ALLOCATION_LOGGING)
983 dataLogF("JSC GC starting collection.\n");
984#endif
985
fpizlo@apple.com0e0d9312013-08-15 20:43:06 +0000986 double before = 0;
987 if (Options::logGC()) {
fpizlo@apple.comed5fc472015-10-17 20:27:43 +0000988 dataLog("[GC: ", capacity() / 1024, " kb ");
fpizlo@apple.com0e0d9312013-08-15 20:43:06 +0000989 before = currentTimeMS();
990 }
991
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000992 double gcStartTime;
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000993
994 if (vm()->typeProfiler()) {
995 DeferGCForAWhile awhile(*this);
996 vm()->typeProfilerLog()->processLogEntries(ASCIILiteral("GC"));
997 }
998
fpizlo@apple.com46050f72016-06-17 04:48:47 +0000999#if ENABLE(JIT)
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001000 {
1001 DeferGCForAWhile awhile(*this);
1002 JITWorklist::instance()->completeAllForVM(*m_vm);
1003 }
fpizlo@apple.com46050f72016-06-17 04:48:47 +00001004#endif // ENABLE(JIT)
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001005
1006 vm()->shadowChicken().update(*vm(), vm()->topCallFrame);
1007
1008 RELEASE_ASSERT(!m_deferralDepth);
1009 ASSERT(vm()->currentThreadIsHoldingAPILock());
1010 RELEASE_ASSERT(vm()->atomicStringTable() == wtfThreadData().atomicStringTable());
1011 ASSERT(m_isSafeToCollect);
1012 RELEASE_ASSERT(!m_collectionScope);
1013
1014 suspendCompilerThreads();
1015 willStartCollection(scope);
1016 {
1017 HelpingGCScope helpingHeapScope(*this);
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00001018
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001019 collectImplTimingScope.setScope(*this);
1020
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00001021 gcStartTime = WTF::monotonicallyIncreasingTime();
1022 if (m_verifier) {
1023 // Verify that live objects from the last GC cycle haven't been corrupted by
1024 // mutators before we begin this new GC cycle.
1025 m_verifier->verify(HeapVerifier::Phase::BeforeGC);
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001026
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00001027 m_verifier->initializeGCCycle();
1028 m_verifier->gatherLiveObjects(HeapVerifier::Phase::BeforeMarking);
1029 }
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001030
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00001031 flushOldStructureIDTables();
1032 stopAllocation();
1033 prepareForMarking();
1034 flushWriteBarrierBuffer();
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001035
sbarati@apple.coma3db4652016-09-20 01:05:50 +00001036 if (HasOwnPropertyCache* cache = vm()->hasOwnPropertyCache())
1037 cache->clear();
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001038
1039 markRoots(gcStartTime, stackOrigin, stackTop, calleeSavedRegisters);
1040
1041 if (m_verifier) {
1042 m_verifier->gatherLiveObjects(HeapVerifier::Phase::AfterMarking);
1043 m_verifier->verify(HeapVerifier::Phase::AfterMarking);
1044 }
1045
1046 if (vm()->typeProfiler())
1047 vm()->typeProfiler()->invalidateTypeSetCache();
1048
1049 reapWeakHandles();
1050 pruneStaleEntriesFromWeakGCMaps();
1051 sweepArrayBuffers();
1052 snapshotUnswept();
1053 finalizeUnconditionalFinalizers();
1054 removeDeadCompilerWorklistEntries();
1055 deleteUnmarkedCompiledCode();
1056 deleteSourceProviderCaches();
1057
1058 notifyIncrementalSweeper();
1059 m_codeBlocks->writeBarrierCurrentlyExecuting(this);
1060 m_codeBlocks->clearCurrentlyExecuting();
1061
1062 prepareForAllocation();
1063 updateAllocationLimits();
mark.lam@apple.com34e46672014-11-20 23:28:41 +00001064 }
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001065 didFinishCollection(gcStartTime);
1066 resumeCompilerThreads();
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00001067 sweepLargeAllocations();
1068
mark.lam@apple.com34e46672014-11-20 23:28:41 +00001069 if (m_verifier) {
1070 m_verifier->trimDeadObjects();
1071 m_verifier->verify(HeapVerifier::Phase::AfterGC);
1072 }
1073
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001074 if (Options::logGC()) {
1075 double after = currentTimeMS();
1076 dataLog(after - before, " ms]\n");
1077 }
fpizlo@apple.com96352992016-09-20 18:12:18 +00001078
1079 if (false) {
1080 dataLog("Heap state after GC:\n");
1081 m_objectSpace.dumpBits();
1082 }
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001083}
1084
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00001085void Heap::sweepLargeAllocations()
1086{
1087 m_objectSpace.sweepLargeAllocations();
1088}
1089
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001090void Heap::suspendCompilerThreads()
1091{
fpizlo@apple.com1b84a422014-02-08 05:06:33 +00001092#if ENABLE(DFG_JIT)
mark.lam@apple.coma9060542014-04-24 00:43:15 +00001093 ASSERT(m_suspendedCompilerWorklists.isEmpty());
fpizlo@apple.com1b84a422014-02-08 05:06:33 +00001094 for (unsigned i = DFG::numberOfWorklists(); i--;) {
mark.lam@apple.coma9060542014-04-24 00:43:15 +00001095 if (DFG::Worklist* worklist = DFG::worklistForIndexOrNull(i)) {
1096 m_suspendedCompilerWorklists.append(worklist);
fpizlo@apple.com1b84a422014-02-08 05:06:33 +00001097 worklist->suspendAllThreads();
mark.lam@apple.coma9060542014-04-24 00:43:15 +00001098 }
mhahnenberg@apple.com7a22bab2013-12-10 19:37:29 +00001099 }
fpizlo@apple.com1b84a422014-02-08 05:06:33 +00001100#endif
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001101}
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +00001102
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001103void Heap::willStartCollection(Optional<CollectionScope> scope)
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001104{
fpizlo@apple.comed5fc472015-10-17 20:27:43 +00001105 if (Options::logGC())
1106 dataLog("=> ");
1107
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001108 if (shouldDoFullCollection(scope)) {
1109 m_collectionScope = CollectionScope::Full;
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +00001110 m_shouldDoFullCollection = false;
1111 if (Options::logGC())
1112 dataLog("FullCollection, ");
1113 } else {
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001114 m_collectionScope = CollectionScope::Eden;
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +00001115 if (Options::logGC())
1116 dataLog("EdenCollection, ");
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +00001117 }
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001118 if (m_collectionScope == CollectionScope::Full) {
mhahnenberg@apple.com0d81ace2014-03-20 01:56:19 +00001119 m_sizeBeforeLastFullCollect = m_sizeAfterLastCollect + m_bytesAllocatedThisCycle;
ggaren@apple.come2ebb8c2015-03-11 21:29:57 +00001120 m_extraMemorySize = 0;
1121 m_deprecatedExtraMemorySize = 0;
commit-queue@webkit.orgeab925d2016-06-23 20:05:23 +00001122#if ENABLE(RESOURCE_USAGE)
1123 m_externalMemorySize = 0;
1124#endif
mhahnenberg@apple.com2b64eec02012-04-18 16:18:32 +00001125
mhahnenberg@apple.com0d81ace2014-03-20 01:56:19 +00001126 if (m_fullActivityCallback)
1127 m_fullActivityCallback->willCollect();
1128 } else {
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001129 ASSERT(m_collectionScope == CollectionScope::Eden);
mhahnenberg@apple.com0d81ace2014-03-20 01:56:19 +00001130 m_sizeBeforeLastEdenCollect = m_sizeAfterLastCollect + m_bytesAllocatedThisCycle;
1131 }
1132
1133 if (m_edenActivityCallback)
1134 m_edenActivityCallback->willCollect();
joepeck@webkit.orgd3b8b372015-10-16 02:15:56 +00001135
1136 for (auto* observer : m_observers)
1137 observer->willGarbageCollect();
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001138}
mhahnenberg@apple.com0eb606f2012-04-20 19:55:21 +00001139
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001140void Heap::flushOldStructureIDTables()
1141{
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001142 m_structureIDTable.flushOldTables();
1143}
1144
1145void Heap::flushWriteBarrierBuffer()
1146{
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001147 if (m_collectionScope == CollectionScope::Eden) {
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001148 m_writeBarrierBuffer.flush(*this);
1149 return;
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +00001150 }
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001151 m_writeBarrierBuffer.reset();
1152}
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +00001153
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001154void Heap::stopAllocation()
1155{
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001156 m_objectSpace.stopAllocating();
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001157}
mhahnenberg@apple.com02e39c72012-10-12 19:38:35 +00001158
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00001159void Heap::prepareForMarking()
1160{
1161 m_objectSpace.prepareForMarking();
1162}
1163
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001164void Heap::reapWeakHandles()
1165{
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001166 m_objectSpace.reapWeakSets();
1167}
ggaren@apple.com39281e22012-05-24 21:18:10 +00001168
akling@apple.com926b1102015-03-10 00:09:39 +00001169void Heap::pruneStaleEntriesFromWeakGCMaps()
1170{
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001171 if (m_collectionScope != CollectionScope::Full)
akling@apple.com926b1102015-03-10 00:09:39 +00001172 return;
1173 for (auto& pruneCallback : m_weakGCMaps.values())
1174 pruneCallback();
1175}
1176
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001177void Heap::sweepArrayBuffers()
1178{
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001179 m_arrayBuffers.sweep();
1180}
ggaren@apple.com6a429812009-12-14 08:13:24 +00001181
fpizlo@apple.com96352992016-09-20 18:12:18 +00001182void Heap::snapshotUnswept()
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001183{
fpizlo@apple.com96352992016-09-20 18:12:18 +00001184 TimingScope timingScope(*this, "Heap::snapshotUnswept");
1185 m_objectSpace.snapshotUnswept();
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001186}
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +00001187
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001188void Heap::deleteSourceProviderCaches()
1189{
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001190 m_vm->clearSourceProviderCaches();
1191}
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +00001192
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001193void Heap::notifyIncrementalSweeper()
1194{
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001195 if (m_collectionScope == CollectionScope::Full) {
akling@apple.come92da672015-04-04 23:16:21 +00001196 if (!m_logicallyEmptyWeakBlocks.isEmpty())
1197 m_indexOfNextLogicallyEmptyWeakBlockToSweep = 0;
akling@apple.come92da672015-04-04 23:16:21 +00001198 }
akling@apple.combfe711c2015-05-20 20:30:42 +00001199
1200 m_sweeper->startSweeping();
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001201}
mhahnenberg@apple.comeb39abc2012-05-31 03:04:00 +00001202
fpizlo@apple.com96352992016-09-20 18:12:18 +00001203void Heap::prepareForAllocation()
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001204{
fpizlo@apple.com96352992016-09-20 18:12:18 +00001205 m_objectSpace.prepareForAllocation();
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001206}
1207
1208void Heap::updateAllocationLimits()
1209{
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00001210 static const bool verbose = false;
1211
1212 if (verbose) {
1213 dataLog("\n");
1214 dataLog("bytesAllocatedThisCycle = ", m_bytesAllocatedThisCycle, "\n");
1215 }
fpizlo@apple.comed5fc472015-10-17 20:27:43 +00001216
1217 // Calculate our current heap size threshold for the purpose of figuring out when we should
1218 // run another collection. This isn't the same as either size() or capacity(), though it should
1219 // be somewhere between the two. The key is to match the size calculations involved calls to
1220 // didAllocate(), while never dangerously underestimating capacity(). In extreme cases of
fpizlo@apple.comd1725cb2016-09-08 22:12:05 +00001221 // fragmentation, we may have size() much smaller than capacity().
fpizlo@apple.comed5fc472015-10-17 20:27:43 +00001222 size_t currentHeapSize = 0;
1223
1224 // For marked space, we use the total number of bytes visited. This matches the logic for
1225 // MarkedAllocator's calls to didAllocate(), which effectively accounts for the total size of
1226 // objects allocated rather than blocks used. This will underestimate capacity(), and in case
1227 // of fragmentation, this may be substantial. Fortunately, marked space rarely fragments because
1228 // cells usually have a narrow range of sizes. So, the underestimation is probably OK.
1229 currentHeapSize += m_totalBytesVisited;
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00001230 if (verbose)
1231 dataLog("totalBytesVisited = ", m_totalBytesVisited, ", currentHeapSize = ", currentHeapSize, "\n");
fpizlo@apple.comed5fc472015-10-17 20:27:43 +00001232
fpizlo@apple.comed5fc472015-10-17 20:27:43 +00001233 // It's up to the user to ensure that extraMemorySize() ends up corresponding to allocation-time
1234 // extra memory reporting.
1235 currentHeapSize += extraMemorySize();
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00001236
1237 if (verbose)
1238 dataLog("extraMemorySize() = ", extraMemorySize(), ", currentHeapSize = ", currentHeapSize, "\n");
fpizlo@apple.comed5fc472015-10-17 20:27:43 +00001239
mhahnenberg@apple.com3a2fb032012-10-05 17:35:49 +00001240 if (Options::gcMaxHeapSize() && currentHeapSize > Options::gcMaxHeapSize())
1241 HeapStatistics::exitWithFailure();
1242
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001243 if (m_collectionScope == CollectionScope::Full) {
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +00001244 // To avoid pathological GC churn in very small and very large heaps, we set
1245 // the new allocation limit based on the current size of the heap, with a
1246 // fixed minimum.
1247 m_maxHeapSize = max(minHeapSize(m_heapType, m_ramSize), proportionalHeapSize(currentHeapSize, m_ramSize));
fpizlo@apple.com595eebd2016-08-24 19:00:37 +00001248 if (verbose)
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00001249 dataLog("Full: maxHeapSize = ", m_maxHeapSize, "\n");
1250 m_maxEdenSize = m_maxHeapSize - currentHeapSize;
1251 if (verbose)
1252 dataLog("Full: maxEdenSize = ", m_maxEdenSize, "\n");
1253 m_sizeAfterLastFullCollect = currentHeapSize;
1254 if (verbose)
1255 dataLog("Full: sizeAfterLastFullCollect = ", currentHeapSize, "\n");
1256 m_bytesAbandonedSinceLastFullCollect = 0;
1257 if (verbose)
1258 dataLog("Full: bytesAbandonedSinceLastFullCollect = ", 0, "\n");
1259 } else {
1260 ASSERT(currentHeapSize >= m_sizeAfterLastCollect);
1261 // Theoretically, we shouldn't ever scan more memory than the heap size we planned to have.
1262 // But we are sloppy, so we have to defend against the overflow.
1263 m_maxEdenSize = currentHeapSize > m_maxHeapSize ? 0 : m_maxHeapSize - currentHeapSize;
1264 if (verbose)
1265 dataLog("Eden: maxEdenSize = ", m_maxEdenSize, "\n");
1266 m_sizeAfterLastEdenCollect = currentHeapSize;
1267 if (verbose)
1268 dataLog("Eden: sizeAfterLastEdenCollect = ", currentHeapSize, "\n");
1269 double edenToOldGenerationRatio = (double)m_maxEdenSize / (double)m_maxHeapSize;
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +00001270 double minEdenToOldGenerationRatio = 1.0 / 3.0;
1271 if (edenToOldGenerationRatio < minEdenToOldGenerationRatio)
1272 m_shouldDoFullCollection = true;
fpizlo@apple.comed5fc472015-10-17 20:27:43 +00001273 // This seems suspect at first, but what it does is ensure that the nursery size is fixed.
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +00001274 m_maxHeapSize += currentHeapSize - m_sizeAfterLastCollect;
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00001275 if (verbose)
1276 dataLog("Eden: maxHeapSize = ", m_maxHeapSize, "\n");
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +00001277 m_maxEdenSize = m_maxHeapSize - currentHeapSize;
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00001278 if (verbose)
1279 dataLog("Eden: maxEdenSize = ", m_maxEdenSize, "\n");
mhahnenberg@apple.com0d81ace2014-03-20 01:56:19 +00001280 if (m_fullActivityCallback) {
1281 ASSERT(currentHeapSize >= m_sizeAfterLastFullCollect);
1282 m_fullActivityCallback->didAllocate(currentHeapSize - m_sizeAfterLastFullCollect);
1283 }
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +00001284 }
1285
ggaren@apple.combd41f7e2013-01-30 00:36:50 +00001286 m_sizeAfterLastCollect = currentHeapSize;
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00001287 if (verbose)
1288 dataLog("sizeAfterLastCollect = ", m_sizeAfterLastCollect, "\n");
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +00001289 m_bytesAllocatedThisCycle = 0;
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001290
1291 if (Options::logGC())
commit-queue@webkit.org847f8252015-10-17 18:42:52 +00001292 dataLog(currentHeapSize / 1024, " kb, ");
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001293}
1294
1295void Heap::didFinishCollection(double gcStartTime)
1296{
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001297 double gcEndTime = WTF::monotonicallyIncreasingTime();
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001298 CollectionScope scope = *m_collectionScope;
1299 if (scope == CollectionScope::Full)
mhahnenberg@apple.com0d81ace2014-03-20 01:56:19 +00001300 m_lastFullGCLength = gcEndTime - gcStartTime;
1301 else
1302 m_lastEdenGCLength = gcEndTime - gcStartTime;
ggaren@apple.comdef139e2012-09-26 02:27:54 +00001303
commit-queue@webkit.orgeab925d2016-06-23 20:05:23 +00001304#if ENABLE(RESOURCE_USAGE)
1305 ASSERT(externalMemorySize() <= extraMemorySize());
1306#endif
1307
mhahnenberg@apple.com3a2fb032012-10-05 17:35:49 +00001308 if (Options::recordGCPauseTimes())
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001309 HeapStatistics::recordGCPauseTime(gcStartTime, gcEndTime);
ggaren@apple.comdef139e2012-09-26 02:27:54 +00001310
1311 if (Options::useZombieMode())
1312 zombifyDeadObjects();
1313
mark.lam@apple.comee3c4102015-10-14 18:57:07 +00001314 if (Options::dumpObjectStatistics())
1315 HeapStatistics::dumpObjectStatistics(this);
mhahnenberg@apple.com040ef242014-04-05 20:05:04 +00001316
commit-queue@webkit.org2ad5c1e2016-03-15 21:48:15 +00001317 if (HeapProfiler* heapProfiler = m_vm->heapProfiler()) {
1318 gatherExtraHeapSnapshotData(*heapProfiler);
1319 removeDeadHeapSnapshotNodes(*heapProfiler);
1320 }
1321
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001322 RELEASE_ASSERT(m_collectionScope);
1323 m_collectionScope = Nullopt;
joepeck@webkit.orgd3b8b372015-10-16 02:15:56 +00001324
1325 for (auto* observer : m_observers)
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001326 observer->didGarbageCollect(scope);
mhahnenberg@apple.comc63eba62014-02-28 16:56:17 +00001327}
1328
1329void Heap::resumeCompilerThreads()
1330{
fpizlo@apple.com1b84a422014-02-08 05:06:33 +00001331#if ENABLE(DFG_JIT)
mark.lam@apple.coma9060542014-04-24 00:43:15 +00001332 for (auto worklist : m_suspendedCompilerWorklists)
1333 worklist->resumeAllThreads();
1334 m_suspendedCompilerWorklists.clear();
fpizlo@apple.com1b84a422014-02-08 05:06:33 +00001335#endif
oliver@apple.com284cc3d2013-07-25 04:00:33 +00001336}
1337
mhahnenberg@apple.com0d81ace2014-03-20 01:56:19 +00001338void Heap::setFullActivityCallback(PassRefPtr<FullGCActivityCallback> activityCallback)
ggaren@apple.com2ccf7a92010-08-03 20:34:17 +00001339{
mhahnenberg@apple.com0d81ace2014-03-20 01:56:19 +00001340 m_fullActivityCallback = activityCallback;
ggaren@apple.com2ccf7a92010-08-03 20:34:17 +00001341}
1342
mhahnenberg@apple.com0d81ace2014-03-20 01:56:19 +00001343void Heap::setEdenActivityCallback(PassRefPtr<EdenGCActivityCallback> activityCallback)
ggaren@apple.comaa64ff32010-12-03 01:16:11 +00001344{
mhahnenberg@apple.com0d81ace2014-03-20 01:56:19 +00001345 m_edenActivityCallback = activityCallback;
1346}
1347
1348GCActivityCallback* Heap::fullActivityCallback()
1349{
1350 return m_fullActivityCallback.get();
1351}
1352
1353GCActivityCallback* Heap::edenActivityCallback()
1354{
1355 return m_edenActivityCallback.get();
ggaren@apple.comaa64ff32010-12-03 01:16:11 +00001356}
1357
gyuyoung.kim@samsung.com05031962014-11-12 03:13:47 +00001358void Heap::setIncrementalSweeper(std::unique_ptr<IncrementalSweeper> sweeper)
dbates@webkit.org0ba27042013-10-18 23:57:24 +00001359{
aestes@apple.com13aae082016-01-02 08:03:08 +00001360 m_sweeper = WTFMove(sweeper);
dbates@webkit.org0ba27042013-10-18 23:57:24 +00001361}
1362
mhahnenberg@apple.comeb39abc2012-05-31 03:04:00 +00001363IncrementalSweeper* Heap::sweeper()
1364{
mhahnenberg@apple.com765a7de2013-04-15 23:17:51 +00001365 return m_sweeper.get();
mhahnenberg@apple.comeb39abc2012-05-31 03:04:00 +00001366}
1367
msaboff@apple.comfb5f4cc2012-05-14 23:47:53 +00001368void Heap::setGarbageCollectionTimerEnabled(bool enable)
1369{
mhahnenberg@apple.com0d81ace2014-03-20 01:56:19 +00001370 if (m_fullActivityCallback)
1371 m_fullActivityCallback->setEnabled(enable);
1372 if (m_edenActivityCallback)
1373 m_edenActivityCallback->setEnabled(enable);
msaboff@apple.comfb5f4cc2012-05-14 23:47:53 +00001374}
1375
mhahnenberg@apple.com8b5cfd32012-04-20 00:05:37 +00001376void Heap::didAllocate(size_t bytes)
1377{
mhahnenberg@apple.com0d81ace2014-03-20 01:56:19 +00001378 if (m_edenActivityCallback)
1379 m_edenActivityCallback->didAllocate(m_bytesAllocatedThisCycle + m_bytesAbandonedSinceLastFullCollect);
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +00001380 m_bytesAllocatedThisCycle += bytes;
mhahnenberg@apple.com8b5cfd32012-04-20 00:05:37 +00001381}
1382
ggaren@apple.com06a8bb62012-09-12 04:08:18 +00001383bool Heap::isValidAllocation(size_t)
ggaren@apple.com99cc9d92011-05-26 21:46:09 +00001384{
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001385 if (!isValidThreadState(m_vm))
ggaren@apple.com99cc9d92011-05-26 21:46:09 +00001386 return false;
1387
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001388 if (isCurrentThreadBusy())
ggaren@apple.com99cc9d92011-05-26 21:46:09 +00001389 return false;
1390
1391 return true;
1392}
1393
ggaren@apple.com75bf76c2011-10-05 22:44:36 +00001394void Heap::addFinalizer(JSCell* cell, Finalizer finalizer)
1395{
commit-queue@webkit.orgd5d496b2015-09-22 12:21:31 +00001396 WeakSet::allocate(cell, &m_finalizerOwner, reinterpret_cast<void*>(finalizer)); // Balanced by FinalizerOwner::finalize().
ggaren@apple.com75bf76c2011-10-05 22:44:36 +00001397}
1398
commit-queue@webkit.orgd5d496b2015-09-22 12:21:31 +00001399void Heap::FinalizerOwner::finalize(Handle<Unknown> handle, void* context)
ggaren@apple.com75bf76c2011-10-05 22:44:36 +00001400{
commit-queue@webkit.orgd5d496b2015-09-22 12:21:31 +00001401 HandleSlot slot = handle.slot();
ggaren@apple.com75bf76c2011-10-05 22:44:36 +00001402 Finalizer finalizer = reinterpret_cast<Finalizer>(context);
commit-queue@webkit.orgd5d496b2015-09-22 12:21:31 +00001403 finalizer(slot->asCell());
1404 WeakSet::deallocate(WeakImpl::asWeakImpl(slot));
ggaren@apple.com75bf76c2011-10-05 22:44:36 +00001405}
1406
ggaren@apple.com5dd393e2015-08-24 21:43:13 +00001407void Heap::addExecutable(ExecutableBase* executable)
mhahnenberg@apple.comcab47522012-03-30 00:36:37 +00001408{
ggaren@apple.com5dd393e2015-08-24 21:43:13 +00001409 m_executables.append(executable);
mhahnenberg@apple.comcab47522012-03-30 00:36:37 +00001410}
1411
cdumez@apple.comccfd3b42015-06-09 22:15:36 +00001412void Heap::collectAllGarbageIfNotDoneRecently()
1413{
1414 if (!m_fullActivityCallback) {
1415 collectAllGarbage();
1416 return;
1417 }
1418
1419 if (m_fullActivityCallback->didSyncGCRecently()) {
1420 // A synchronous GC was already requested recently so we merely accelerate next collection.
1421 reportAbandonedObjectGraph();
1422 return;
1423 }
1424
1425 m_fullActivityCallback->setDidSyncGCRecently();
1426 collectAllGarbage();
1427}
1428
ggaren@apple.comdef139e2012-09-26 02:27:54 +00001429class Zombify : public MarkedBlock::VoidFunctor {
mhahnenberg@apple.com66b96f22012-09-07 05:53:25 +00001430public:
fpizlo@apple.comaeddff92016-07-18 21:33:45 +00001431 inline void visit(HeapCell* cell) const
mhahnenberg@apple.com66b96f22012-09-07 05:53:25 +00001432 {
zandobersek@gmail.comc5b35d32016-10-21 06:00:48 +00001433 void** current = reinterpret_cast_ptr<void**>(cell);
mhahnenberg@apple.com66b96f22012-09-07 05:53:25 +00001434
1435 // We want to maintain zapped-ness because that's how we know if we've called
1436 // the destructor.
1437 if (cell->isZapped())
1438 current++;
1439
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00001440 void* limit = static_cast<void*>(reinterpret_cast<char*>(cell) + cell->cellSize());
mhahnenberg@apple.com66b96f22012-09-07 05:53:25 +00001441 for (; current < limit; current++)
mark.lam@apple.comd7e9e162014-05-07 22:00:10 +00001442 *current = zombifiedBits;
mhahnenberg@apple.com66b96f22012-09-07 05:53:25 +00001443 }
fpizlo@apple.comaeddff92016-07-18 21:33:45 +00001444 IterationStatus operator()(HeapCell* cell, HeapCell::Kind) const
mark.lam@apple.comf535b592015-04-22 20:05:06 +00001445 {
1446 visit(cell);
1447 return IterationStatus::Continue;
1448 }
mhahnenberg@apple.com66b96f22012-09-07 05:53:25 +00001449};
1450
1451void Heap::zombifyDeadObjects()
1452{
ggaren@apple.comdef139e2012-09-26 02:27:54 +00001453 // Sweep now because destructors will crash once we're zombified.
fpizlo@apple.com96352992016-09-20 18:12:18 +00001454 m_objectSpace.sweep();
mhahnenberg@apple.combee96a32013-09-16 19:48:48 +00001455 HeapIterationScope iterationScope(*this);
fpizlo@apple.comaeddff92016-07-18 21:33:45 +00001456 m_objectSpace.forEachDeadCell(iterationScope, Zombify());
mhahnenberg@apple.com66b96f22012-09-07 05:53:25 +00001457}
1458
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +00001459void Heap::flushWriteBarrierBuffer(JSCell* cell)
1460{
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +00001461 m_writeBarrierBuffer.flush(*this);
1462 m_writeBarrierBuffer.add(cell);
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +00001463}
1464
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001465bool Heap::shouldDoFullCollection(Optional<CollectionScope> scope) const
mhahnenberg@apple.com60e82922014-02-20 22:53:21 +00001466{
mark.lam@apple.comee3c4102015-10-14 18:57:07 +00001467 if (!Options::useGenerationalGC())
mhahnenberg@apple.com0d81ace2014-03-20 01:56:19 +00001468 return true;
1469
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001470 if (!scope)
mhahnenberg@apple.com0d81ace2014-03-20 01:56:19 +00001471 return m_shouldDoFullCollection;
fpizlo@apple.comea379af2016-10-21 02:17:35 +00001472 return *scope == CollectionScope::Full;
mhahnenberg@apple.com60e82922014-02-20 22:53:21 +00001473}
1474
akling@apple.come92da672015-04-04 23:16:21 +00001475void Heap::addLogicallyEmptyWeakBlock(WeakBlock* block)
1476{
1477 m_logicallyEmptyWeakBlocks.append(block);
1478}
1479
1480void Heap::sweepAllLogicallyEmptyWeakBlocks()
1481{
1482 if (m_logicallyEmptyWeakBlocks.isEmpty())
1483 return;
1484
1485 m_indexOfNextLogicallyEmptyWeakBlockToSweep = 0;
1486 while (sweepNextLogicallyEmptyWeakBlock()) { }
1487}
1488
1489bool Heap::sweepNextLogicallyEmptyWeakBlock()
1490{
1491 if (m_indexOfNextLogicallyEmptyWeakBlockToSweep == WTF::notFound)
1492 return false;
1493
1494 WeakBlock* block = m_logicallyEmptyWeakBlocks[m_indexOfNextLogicallyEmptyWeakBlockToSweep];
1495
1496 block->sweep();
1497 if (block->isEmpty()) {
1498 std::swap(m_logicallyEmptyWeakBlocks[m_indexOfNextLogicallyEmptyWeakBlockToSweep], m_logicallyEmptyWeakBlocks.last());
1499 m_logicallyEmptyWeakBlocks.removeLast();
akling@apple.com43fb3522015-11-01 02:29:47 +00001500 WeakBlock::destroy(*this, block);
akling@apple.come92da672015-04-04 23:16:21 +00001501 } else
1502 m_indexOfNextLogicallyEmptyWeakBlockToSweep++;
1503
1504 if (m_indexOfNextLogicallyEmptyWeakBlockToSweep >= m_logicallyEmptyWeakBlocks.size()) {
1505 m_indexOfNextLogicallyEmptyWeakBlockToSweep = WTF::notFound;
1506 return false;
1507 }
1508
1509 return true;
1510}
1511
fpizlo@apple.com42e88d02015-09-23 01:35:49 +00001512size_t Heap::threadVisitCount()
1513{
1514 unsigned long result = 0;
fpizlo@apple.com5f866062015-09-26 18:07:09 +00001515 for (auto& parallelVisitor : m_parallelSlotVisitors)
1516 result += parallelVisitor->visitCount();
fpizlo@apple.com42e88d02015-09-23 01:35:49 +00001517 return result;
1518}
1519
1520size_t Heap::threadBytesVisited()
1521{
1522 size_t result = 0;
fpizlo@apple.com5f866062015-09-26 18:07:09 +00001523 for (auto& parallelVisitor : m_parallelSlotVisitors)
1524 result += parallelVisitor->bytesVisited();
fpizlo@apple.com42e88d02015-09-23 01:35:49 +00001525 return result;
1526}
1527
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00001528void Heap::forEachCodeBlockImpl(const ScopedLambda<bool(CodeBlock*)>& func)
1529{
1530 // We don't know the full set of CodeBlocks until compilation has terminated.
1531 completeAllJITPlans();
1532
1533 return m_codeBlocks->iterate(func);
1534}
1535
fpizlo@apple.com9a175952016-09-28 21:55:53 +00001536void Heap::writeBarrierSlowPath(const JSCell* from)
1537{
1538 if (UNLIKELY(barrierShouldBeFenced())) {
1539 // In this case, the barrierThreshold is the tautological threshold, so from could still be
1540 // not black. But we can't know for sure until we fire off a fence.
1541 WTF::storeLoadFence();
fpizlo@apple.com261fc222016-10-12 23:56:34 +00001542 if (from->cellState() != CellState::AnthraciteOrBlack)
fpizlo@apple.com9a175952016-09-28 21:55:53 +00001543 return;
1544 }
1545
1546 addToRememberedSet(from);
1547}
1548
fpizlo@apple.com4dbb3512016-10-22 19:34:46 +00001549bool Heap::shouldCollect()
1550{
1551 if (isDeferred())
1552 return false;
1553 if (!m_isSafeToCollect)
1554 return false;
1555 if (collectionScope() || mutatorState() == MutatorState::HelpingGC)
1556 return false;
1557 if (Options::gcMaxHeapSize())
1558 return m_bytesAllocatedThisCycle > Options::gcMaxHeapSize();
1559 return m_bytesAllocatedThisCycle > m_maxEdenSize;
1560}
1561
1562bool Heap::isCurrentThreadBusy()
1563{
1564 return mayBeGCThread() || mutatorState() != MutatorState::Running;
1565}
1566
1567void Heap::reportExtraMemoryVisited(CellState oldState, size_t size)
1568{
1569 // We don't want to double-count the extra memory that was reported in previous collections.
1570 if (collectionScope() == CollectionScope::Eden && oldState == CellState::OldGrey)
1571 return;
1572
1573 size_t* counter = &m_extraMemorySize;
1574
1575 for (;;) {
1576 size_t oldSize = *counter;
fpizlo@apple.comafa9d882016-11-01 03:10:00 +00001577 if (WTF::atomicCompareExchangeWeakRelaxed(counter, oldSize, oldSize + size))
fpizlo@apple.com4dbb3512016-10-22 19:34:46 +00001578 return;
1579 }
1580}
1581
1582#if ENABLE(RESOURCE_USAGE)
1583void Heap::reportExternalMemoryVisited(CellState oldState, size_t size)
1584{
1585 // We don't want to double-count the external memory that was reported in previous collections.
1586 if (collectionScope() == CollectionScope::Eden && oldState == CellState::OldGrey)
1587 return;
1588
1589 size_t* counter = &m_externalMemorySize;
1590
1591 for (;;) {
1592 size_t oldSize = *counter;
fpizlo@apple.comafa9d882016-11-01 03:10:00 +00001593 if (WTF::atomicCompareExchangeWeakRelaxed(counter, oldSize, oldSize + size))
fpizlo@apple.com4dbb3512016-10-22 19:34:46 +00001594 return;
1595 }
1596}
1597#endif
1598
1599bool Heap::collectIfNecessaryOrDefer(GCDeferralContext* deferralContext)
1600{
1601 if (!shouldCollect())
1602 return false;
1603
1604 if (deferralContext)
1605 deferralContext->m_shouldGC = true;
1606 else
1607 collect();
1608 return true;
1609}
1610
1611void Heap::collectAccordingToDeferGCProbability()
1612{
1613 if (isDeferred() || !m_isSafeToCollect || collectionScope() || mutatorState() == MutatorState::HelpingGC)
1614 return;
1615
1616 if (randomNumber() < Options::deferGCProbability()) {
1617 collect();
1618 return;
1619 }
1620
1621 // If our coin flip told us not to GC, we still might GC,
1622 // but we GC according to our memory pressure markers.
1623 collectIfNecessaryOrDefer();
1624}
1625
1626void Heap::decrementDeferralDepthAndGCIfNeeded()
1627{
1628 decrementDeferralDepth();
1629 if (UNLIKELY(Options::deferGCShouldCollectWithProbability()))
1630 collectAccordingToDeferGCProbability();
1631 else
1632 collectIfNecessaryOrDefer();
1633}
1634
1635void Heap::registerWeakGCMap(void* weakGCMap, std::function<void()> pruningCallback)
1636{
1637 m_weakGCMaps.add(weakGCMap, WTFMove(pruningCallback));
1638}
1639
1640void Heap::unregisterWeakGCMap(void* weakGCMap)
1641{
1642 m_weakGCMaps.remove(weakGCMap);
1643}
1644
1645void Heap::didAllocateBlock(size_t capacity)
1646{
1647#if ENABLE(RESOURCE_USAGE)
1648 m_blockBytesAllocated += capacity;
1649#else
1650 UNUSED_PARAM(capacity);
1651#endif
1652}
1653
1654void Heap::didFreeBlock(size_t capacity)
1655{
1656#if ENABLE(RESOURCE_USAGE)
1657 m_blockBytesAllocated -= capacity;
1658#else
1659 UNUSED_PARAM(capacity);
1660#endif
1661}
1662
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +00001663} // namespace JSC