09611aa0fbb067af4b56c312515ee769a14972bd
[WebKit-https.git] / Source / JavaScriptCore / heap / Heap.cpp
1 /*
2  *  Copyright (C) 2003-2009, 2011, 2013-2016 Apple Inc. All rights reserved.
3  *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
4  *
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
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  *
19  */
20
21 #include "config.h"
22 #include "Heap.h"
23
24 #include "CodeBlock.h"
25 #include "ConservativeRoots.h"
26 #include "CopiedSpace.h"
27 #include "CopiedSpaceInlines.h"
28 #include "CopyVisitorInlines.h"
29 #include "DFGWorklist.h"
30 #include "EdenGCActivityCallback.h"
31 #include "FullGCActivityCallback.h"
32 #include "GCActivityCallback.h"
33 #include "GCIncomingRefCountedSetInlines.h"
34 #include "HeapHelperPool.h"
35 #include "HeapIterationScope.h"
36 #include "HeapProfiler.h"
37 #include "HeapRootVisitor.h"
38 #include "HeapSnapshot.h"
39 #include "HeapStatistics.h"
40 #include "HeapVerifier.h"
41 #include "IncrementalSweeper.h"
42 #include "Interpreter.h"
43 #include "JITWorklist.h"
44 #include "JSCInlines.h"
45 #include "JSGlobalObject.h"
46 #include "JSLock.h"
47 #include "JSVirtualMachineInternal.h"
48 #include "SamplingProfiler.h"
49 #include "ShadowChicken.h"
50 #include "TypeProfilerLog.h"
51 #include "UnlinkedCodeBlock.h"
52 #include "VM.h"
53 #include "WeakSetInlines.h"
54 #include <algorithm>
55 #include <wtf/CurrentTime.h>
56 #include <wtf/MainThread.h>
57 #include <wtf/ParallelVectorIterator.h>
58 #include <wtf/ProcessID.h>
59 #include <wtf/RAMSize.h>
60
61 #if USE(FOUNDATION)
62 #if __has_include(<objc/objc-internal.h>)
63 #include <objc/objc-internal.h>
64 #else
65 extern "C" void* objc_autoreleasePoolPush(void);
66 extern "C" void objc_autoreleasePoolPop(void *context);
67 #endif
68 #endif // USE(FOUNDATION)
69
70 using namespace std;
71
72 namespace JSC {
73
74 namespace {
75
76 static const size_t largeHeapSize = 32 * MB; // About 1.5X the average webpage.
77 static const size_t smallHeapSize = 1 * MB; // Matches the FastMalloc per-thread cache.
78
79 #define ENABLE_GC_LOGGING 0
80
81 #if ENABLE(GC_LOGGING)
82 #if COMPILER(CLANG)
83 #define DEFINE_GC_LOGGING_GLOBAL(type, name, arguments) \
84 _Pragma("clang diagnostic push") \
85 _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") \
86 _Pragma("clang diagnostic ignored \"-Wexit-time-destructors\"") \
87 static type name arguments; \
88 _Pragma("clang diagnostic pop")
89 #else
90 #define DEFINE_GC_LOGGING_GLOBAL(type, name, arguments) \
91 static type name arguments;
92 #endif // COMPILER(CLANG)
93
94 struct GCTimer {
95     GCTimer(const char* name)
96         : name(name)
97     {
98     }
99     ~GCTimer()
100     {
101         logData(allCollectionData, "(All)");
102         logData(edenCollectionData, "(Eden)");
103         logData(fullCollectionData, "(Full)");
104     }
105
106     struct TimeRecord {
107         TimeRecord()
108             : time(0)
109             , min(std::numeric_limits<double>::infinity())
110             , max(0)
111             , count(0)
112         {
113         }
114
115         double time;
116         double min;
117         double max;
118         size_t count;
119     };
120
121     void logData(const TimeRecord& data, const char* extra)
122     {
123         dataLogF("[%d] %s (Parent: %s) %s: %.2lfms (avg. %.2lf, min. %.2lf, max. %.2lf, count %lu)\n", 
124             getCurrentProcessID(),
125             name,
126             parent ? parent->name : "nullptr",
127             extra, 
128             data.time * 1000, 
129             data.time * 1000 / data.count, 
130             data.min * 1000, 
131             data.max * 1000,
132             data.count);
133     }
134
135     void updateData(TimeRecord& data, double duration)
136     {
137         if (duration < data.min)
138             data.min = duration;
139         if (duration > data.max)
140             data.max = duration;
141         data.count++;
142         data.time += duration;
143     }
144
145     void didFinishPhase(HeapOperation collectionType, double duration)
146     {
147         TimeRecord& data = collectionType == EdenCollection ? edenCollectionData : fullCollectionData;
148         updateData(data, duration);
149         updateData(allCollectionData, duration);
150     }
151
152     static GCTimer* s_currentGlobalTimer;
153
154     TimeRecord allCollectionData;
155     TimeRecord fullCollectionData;
156     TimeRecord edenCollectionData;
157     const char* name;
158     GCTimer* parent { nullptr };
159 };
160
161 GCTimer* GCTimer::s_currentGlobalTimer = nullptr;
162
163 struct GCTimerScope {
164     GCTimerScope(GCTimer& timer, HeapOperation collectionType)
165         : timer(timer)
166         , start(WTF::monotonicallyIncreasingTime())
167         , collectionType(collectionType)
168     {
169         timer.parent = GCTimer::s_currentGlobalTimer;
170         GCTimer::s_currentGlobalTimer = &timer;
171     }
172     ~GCTimerScope()
173     {
174         double delta = WTF::monotonicallyIncreasingTime() - start;
175         timer.didFinishPhase(collectionType, delta);
176         GCTimer::s_currentGlobalTimer = timer.parent;
177     }
178     GCTimer& timer;
179     double start;
180     HeapOperation collectionType;
181 };
182
183 struct GCCounter {
184     GCCounter(const char* name)
185         : name(name)
186         , count(0)
187         , total(0)
188         , min(10000000)
189         , max(0)
190     {
191     }
192     
193     void add(size_t amount)
194     {
195         count++;
196         total += amount;
197         if (amount < min)
198             min = amount;
199         if (amount > max)
200             max = amount;
201     }
202     ~GCCounter()
203     {
204         dataLogF("[%d] %s: %zu values (avg. %zu, min. %zu, max. %zu)\n", getCurrentProcessID(), name, total, total / count, min, max);
205     }
206     const char* name;
207     size_t count;
208     size_t total;
209     size_t min;
210     size_t max;
211 };
212
213 #define GCPHASE(name) DEFINE_GC_LOGGING_GLOBAL(GCTimer, name##Timer, (#name)); GCTimerScope name##TimerScope(name##Timer, m_operationInProgress)
214 #define GCCOUNTER(name, value) do { DEFINE_GC_LOGGING_GLOBAL(GCCounter, name##Counter, (#name)); name##Counter.add(value); } while (false)
215     
216 #else
217
218 #define GCPHASE(name) do { } while (false)
219 #define GCCOUNTER(name, value) do { } while (false)
220 #endif
221
222 static inline size_t minHeapSize(HeapType heapType, size_t ramSize)
223 {
224     if (heapType == LargeHeap)
225         return min(largeHeapSize, ramSize / 4);
226     return smallHeapSize;
227 }
228
229 static inline size_t proportionalHeapSize(size_t heapSize, size_t ramSize)
230 {
231     // Try to stay under 1/2 RAM size to leave room for the DOM, rendering, networking, etc.
232     if (heapSize < ramSize / 4)
233         return 2 * heapSize;
234     if (heapSize < ramSize / 2)
235         return 1.5 * heapSize;
236     return 1.25 * heapSize;
237 }
238
239 static inline bool isValidSharedInstanceThreadState(VM* vm)
240 {
241     return vm->currentThreadIsHoldingAPILock();
242 }
243
244 static inline bool isValidThreadState(VM* vm)
245 {
246     if (vm->atomicStringTable() != wtfThreadData().atomicStringTable())
247         return false;
248
249     if (vm->isSharedInstance() && !isValidSharedInstanceThreadState(vm))
250         return false;
251
252     return true;
253 }
254
255 static inline void recordType(TypeCountSet& set, JSCell* cell)
256 {
257     const char* typeName = "[unknown]";
258     const ClassInfo* info = cell->classInfo();
259     if (info && info->className)
260         typeName = info->className;
261     set.add(typeName);
262 }
263
264 } // anonymous namespace
265
266 Heap::Heap(VM* vm, HeapType heapType)
267     : m_heapType(heapType)
268     , m_ramSize(Options::forceRAMSize() ? Options::forceRAMSize() : ramSize())
269     , m_minBytesPerCycle(minHeapSize(m_heapType, m_ramSize))
270     , m_sizeAfterLastCollect(0)
271     , m_sizeAfterLastFullCollect(0)
272     , m_sizeBeforeLastFullCollect(0)
273     , m_sizeAfterLastEdenCollect(0)
274     , m_sizeBeforeLastEdenCollect(0)
275     , m_bytesAllocatedThisCycle(0)
276     , m_bytesAbandonedSinceLastFullCollect(0)
277     , m_maxEdenSize(m_minBytesPerCycle)
278     , m_maxHeapSize(m_minBytesPerCycle)
279     , m_shouldDoFullCollection(false)
280     , m_totalBytesVisited(0)
281     , m_totalBytesCopied(0)
282     , m_operationInProgress(NoOperation)
283     , m_objectSpace(this)
284     , m_storageSpace(this)
285     , m_extraMemorySize(0)
286     , m_deprecatedExtraMemorySize(0)
287     , m_machineThreads(this)
288     , m_slotVisitor(*this)
289     , m_handleSet(vm)
290     , m_isSafeToCollect(false)
291     , m_writeBarrierBuffer(256)
292     , m_vm(vm)
293     // We seed with 10ms so that GCActivityCallback::didAllocate doesn't continuously 
294     // schedule the timer if we've never done a collection.
295     , m_lastFullGCLength(0.01)
296     , m_lastEdenGCLength(0.01)
297     , m_fullActivityCallback(GCActivityCallback::createFullTimer(this))
298     , m_edenActivityCallback(GCActivityCallback::createEdenTimer(this))
299 #if USE(CF)
300     , m_sweeper(std::make_unique<IncrementalSweeper>(this, CFRunLoopGetCurrent()))
301 #else
302     , m_sweeper(std::make_unique<IncrementalSweeper>(this))
303 #endif
304     , m_deferralDepth(0)
305 #if USE(FOUNDATION)
306     , m_delayedReleaseRecursionCount(0)
307 #endif
308     , m_helperClient(&heapHelperPool())
309 {
310     m_storageSpace.init();
311     if (Options::verifyHeap())
312         m_verifier = std::make_unique<HeapVerifier>(this, Options::numberOfGCCyclesToRecordForVerification());
313 }
314
315 Heap::~Heap()
316 {
317     for (WeakBlock* block : m_logicallyEmptyWeakBlocks)
318         WeakBlock::destroy(*this, block);
319 }
320
321 bool Heap::isPagedOut(double deadline)
322 {
323     return m_objectSpace.isPagedOut(deadline) || m_storageSpace.isPagedOut(deadline);
324 }
325
326 // The VM is being destroyed and the collector will never run again.
327 // Run all pending finalizers now because we won't get another chance.
328 void Heap::lastChanceToFinalize()
329 {
330     RELEASE_ASSERT(!m_vm->entryScope);
331     RELEASE_ASSERT(m_operationInProgress == NoOperation);
332
333     m_arrayBuffers.lastChanceToFinalize();
334     m_codeBlocks.lastChanceToFinalize();
335     m_objectSpace.lastChanceToFinalize();
336     releaseDelayedReleasedObjects();
337
338     sweepAllLogicallyEmptyWeakBlocks();
339 }
340
341 void Heap::releaseDelayedReleasedObjects()
342 {
343 #if USE(FOUNDATION)
344     // We need to guard against the case that releasing an object can create more objects due to the
345     // release calling into JS. When those JS call(s) exit and all locks are being dropped we end up
346     // back here and could try to recursively release objects. We guard that with a recursive entry
347     // count. Only the initial call will release objects, recursive calls simple return and let the
348     // the initial call to the function take care of any objects created during release time.
349     // This also means that we need to loop until there are no objects in m_delayedReleaseObjects
350     // and use a temp Vector for the actual releasing.
351     if (!m_delayedReleaseRecursionCount++) {
352         while (!m_delayedReleaseObjects.isEmpty()) {
353             ASSERT(m_vm->currentThreadIsHoldingAPILock());
354
355             Vector<RetainPtr<CFTypeRef>> objectsToRelease = WTFMove(m_delayedReleaseObjects);
356
357             {
358                 // We need to drop locks before calling out to arbitrary code.
359                 JSLock::DropAllLocks dropAllLocks(m_vm);
360
361                 void* context = objc_autoreleasePoolPush();
362                 objectsToRelease.clear();
363                 objc_autoreleasePoolPop(context);
364             }
365         }
366     }
367     m_delayedReleaseRecursionCount--;
368 #endif
369 }
370
371 void Heap::reportExtraMemoryAllocatedSlowCase(size_t size)
372 {
373     didAllocate(size);
374     collectIfNecessaryOrDefer();
375 }
376
377 void Heap::deprecatedReportExtraMemorySlowCase(size_t size)
378 {
379     m_deprecatedExtraMemorySize += size;
380     reportExtraMemoryAllocatedSlowCase(size);
381 }
382
383 void Heap::reportAbandonedObjectGraph()
384 {
385     // Our clients don't know exactly how much memory they
386     // are abandoning so we just guess for them.
387     size_t abandonedBytes = static_cast<size_t>(0.1 * capacity());
388
389     // We want to accelerate the next collection. Because memory has just 
390     // been abandoned, the next collection has the potential to 
391     // be more profitable. Since allocation is the trigger for collection, 
392     // we hasten the next collection by pretending that we've allocated more memory. 
393     if (m_fullActivityCallback) {
394         m_fullActivityCallback->didAllocate(
395             m_sizeAfterLastCollect - m_sizeAfterLastFullCollect + m_bytesAllocatedThisCycle + m_bytesAbandonedSinceLastFullCollect);
396     }
397     m_bytesAbandonedSinceLastFullCollect += abandonedBytes;
398 }
399
400 void Heap::protect(JSValue k)
401 {
402     ASSERT(k);
403     ASSERT(m_vm->currentThreadIsHoldingAPILock());
404
405     if (!k.isCell())
406         return;
407
408     m_protectedValues.add(k.asCell());
409 }
410
411 bool Heap::unprotect(JSValue k)
412 {
413     ASSERT(k);
414     ASSERT(m_vm->currentThreadIsHoldingAPILock());
415
416     if (!k.isCell())
417         return false;
418
419     return m_protectedValues.remove(k.asCell());
420 }
421
422 void Heap::addReference(JSCell* cell, ArrayBuffer* buffer)
423 {
424     if (m_arrayBuffers.addReference(cell, buffer)) {
425         collectIfNecessaryOrDefer();
426         didAllocate(buffer->gcSizeEstimateInBytes());
427     }
428 }
429
430 void Heap::harvestWeakReferences()
431 {
432     m_slotVisitor.harvestWeakReferences();
433 }
434
435 void Heap::finalizeUnconditionalFinalizers()
436 {
437     GCPHASE(FinalizeUnconditionalFinalizers);
438     m_slotVisitor.finalizeUnconditionalFinalizers();
439 }
440
441 void Heap::willStartIterating()
442 {
443     m_objectSpace.willStartIterating();
444 }
445
446 void Heap::didFinishIterating()
447 {
448     m_objectSpace.didFinishIterating();
449 }
450
451 void Heap::completeAllJITPlans()
452 {
453 #if ENABLE(JIT)
454     JITWorklist::instance()->completeAllForVM(*m_vm);
455 #endif // ENABLE(JIT)
456 #if ENABLE(DFG_JIT)
457     DFG::completeAllPlansForVM(*m_vm);
458 #endif
459 }
460
461 void Heap::markRoots(double gcStartTime, void* stackOrigin, void* stackTop, MachineThreads::RegisterState& calleeSavedRegisters)
462 {
463     GCPHASE(MarkRoots);
464     ASSERT(isValidThreadState(m_vm));
465
466     // We gather conservative roots before clearing mark bits because conservative
467     // gathering uses the mark bits to determine whether a reference is valid.
468     ConservativeRoots conservativeRoots(&m_objectSpace.blocks(), &m_storageSpace);
469     gatherStackRoots(conservativeRoots, stackOrigin, stackTop, calleeSavedRegisters);
470     gatherJSStackRoots(conservativeRoots);
471     gatherScratchBufferRoots(conservativeRoots);
472
473 #if ENABLE(DFG_JIT)
474     DFG::rememberCodeBlocks(*m_vm);
475 #endif
476
477 #if ENABLE(SAMPLING_PROFILER)
478     if (SamplingProfiler* samplingProfiler = m_vm->samplingProfiler()) {
479         // Note that we need to own the lock from now until we're done
480         // marking the SamplingProfiler's data because once we verify the
481         // SamplingProfiler's stack traces, we don't want it to accumulate
482         // more stack traces before we get the chance to mark it.
483         // This lock is released inside visitSamplingProfiler().
484         samplingProfiler->getLock().lock();
485         samplingProfiler->processUnverifiedStackTraces();
486     }
487 #endif // ENABLE(SAMPLING_PROFILER)
488
489     if (m_operationInProgress == FullCollection) {
490         m_opaqueRoots.clear();
491         m_slotVisitor.clearMarkStack();
492     }
493
494     clearLivenessData();
495
496     m_parallelMarkersShouldExit = false;
497
498     m_helperClient.setFunction(
499         [this] () {
500             SlotVisitor* slotVisitor;
501             {
502                 LockHolder locker(m_parallelSlotVisitorLock);
503                 if (m_availableParallelSlotVisitors.isEmpty()) {
504                     std::unique_ptr<SlotVisitor> newVisitor =
505                         std::make_unique<SlotVisitor>(*this);
506                     slotVisitor = newVisitor.get();
507                     m_parallelSlotVisitors.append(WTFMove(newVisitor));
508                 } else
509                     slotVisitor = m_availableParallelSlotVisitors.takeLast();
510             }
511
512             WTF::registerGCThread();
513
514             {
515                 ParallelModeEnabler parallelModeEnabler(*slotVisitor);
516                 slotVisitor->didStartMarking();
517                 slotVisitor->drainFromShared(SlotVisitor::SlaveDrain);
518             }
519
520             {
521                 LockHolder locker(m_parallelSlotVisitorLock);
522                 m_availableParallelSlotVisitors.append(slotVisitor);
523             }
524         });
525
526     m_slotVisitor.didStartMarking();
527     
528     HeapRootVisitor heapRootVisitor(m_slotVisitor);
529
530     {
531         ParallelModeEnabler enabler(m_slotVisitor);
532
533         m_slotVisitor.donateAndDrain();
534         visitExternalRememberedSet();
535         visitSmallStrings();
536         visitConservativeRoots(conservativeRoots);
537         visitProtectedObjects(heapRootVisitor);
538         visitArgumentBuffers(heapRootVisitor);
539         visitException(heapRootVisitor);
540         visitStrongHandles(heapRootVisitor);
541         visitHandleStack(heapRootVisitor);
542         visitSamplingProfiler();
543         visitShadowChicken();
544         traceCodeBlocksAndJITStubRoutines();
545         converge();
546     }
547
548     // Weak references must be marked last because their liveness depends on
549     // the liveness of the rest of the object graph.
550     visitWeakHandles(heapRootVisitor);
551
552     {
553         std::lock_guard<Lock> lock(m_markingMutex);
554         m_parallelMarkersShouldExit = true;
555         m_markingConditionVariable.notifyAll();
556     }
557     m_helperClient.finish();
558     updateObjectCounts(gcStartTime);
559     resetVisitors();
560 }
561
562 void Heap::copyBackingStores()
563 {
564     GCPHASE(CopyBackingStores);
565     if (m_operationInProgress == EdenCollection)
566         m_storageSpace.startedCopying<EdenCollection>();
567     else {
568         ASSERT(m_operationInProgress == FullCollection);
569         m_storageSpace.startedCopying<FullCollection>();
570     }
571
572     if (m_storageSpace.shouldDoCopyPhase()) {
573         if (m_operationInProgress == EdenCollection) {
574             // Reset the vector to be empty, but don't throw away the backing store.
575             m_blocksToCopy.shrink(0);
576             for (CopiedBlock* block = m_storageSpace.m_newGen.fromSpace->head(); block; block = block->next())
577                 m_blocksToCopy.append(block);
578         } else {
579             ASSERT(m_operationInProgress == FullCollection);
580             WTF::copyToVector(m_storageSpace.m_blockSet, m_blocksToCopy);
581         }
582
583         ParallelVectorIterator<Vector<CopiedBlock*>> iterator(
584             m_blocksToCopy, s_blockFragmentLength);
585
586         // Note that it's safe to use the [&] capture list here, even though we're creating a task
587         // that other threads run. That's because after runFunctionInParallel() returns, the task
588         // we have created is not going to be running anymore. Hence, everything on the stack here
589         // outlives the task.
590         m_helperClient.runFunctionInParallel(
591             [&] () {
592                 CopyVisitor copyVisitor(*this);
593                 
594                 iterator.iterate(
595                     [&] (CopiedBlock* block) {
596                         if (!block->hasWorkList())
597                             return;
598                         
599                         CopyWorkList& workList = block->workList();
600                         for (CopyWorklistItem item : workList) {
601                             if (item.token() == ButterflyCopyToken) {
602                                 JSObject::copyBackingStore(
603                                     item.cell(), copyVisitor, ButterflyCopyToken);
604                                 continue;
605                             }
606                             
607                             item.cell()->methodTable()->copyBackingStore(
608                                 item.cell(), copyVisitor, item.token());
609                         }
610                         
611                         ASSERT(!block->liveBytes());
612                         m_storageSpace.recycleEvacuatedBlock(block, m_operationInProgress);
613                     });
614             });
615     }
616     
617     m_storageSpace.doneCopying();
618 }
619
620 void Heap::gatherStackRoots(ConservativeRoots& roots, void* stackOrigin, void* stackTop, MachineThreads::RegisterState& calleeSavedRegisters)
621 {
622     GCPHASE(GatherStackRoots);
623     m_jitStubRoutines.clearMarks();
624     m_machineThreads.gatherConservativeRoots(roots, m_jitStubRoutines, m_codeBlocks, stackOrigin, stackTop, calleeSavedRegisters);
625 }
626
627 void Heap::gatherJSStackRoots(ConservativeRoots& roots)
628 {
629 #if !ENABLE(JIT)
630     GCPHASE(GatherJSStackRoots);
631     m_vm->interpreter->cloopStack().gatherConservativeRoots(roots, m_jitStubRoutines, m_codeBlocks);
632 #else
633     UNUSED_PARAM(roots);
634 #endif
635 }
636
637 void Heap::gatherScratchBufferRoots(ConservativeRoots& roots)
638 {
639 #if ENABLE(DFG_JIT)
640     GCPHASE(GatherScratchBufferRoots);
641     m_vm->gatherConservativeRoots(roots);
642 #else
643     UNUSED_PARAM(roots);
644 #endif
645 }
646
647 void Heap::clearLivenessData()
648 {
649     GCPHASE(ClearLivenessData);
650     if (m_operationInProgress == FullCollection)
651         m_codeBlocks.clearMarksForFullCollection();
652
653     m_objectSpace.clearNewlyAllocated();
654     m_objectSpace.clearMarks();
655 }
656
657 void Heap::visitExternalRememberedSet()
658 {
659 #if JSC_OBJC_API_ENABLED
660     scanExternalRememberedSet(*m_vm, m_slotVisitor);
661 #endif
662 }
663
664 void Heap::visitSmallStrings()
665 {
666     GCPHASE(VisitSmallStrings);
667     if (!m_vm->smallStrings.needsToBeVisited(m_operationInProgress))
668         return;
669
670     m_vm->smallStrings.visitStrongReferences(m_slotVisitor);
671     if (Options::logGC() == GCLogging::Verbose)
672         dataLog("Small strings:\n", m_slotVisitor);
673     m_slotVisitor.donateAndDrain();
674 }
675
676 void Heap::visitConservativeRoots(ConservativeRoots& roots)
677 {
678     GCPHASE(VisitConservativeRoots);
679     m_slotVisitor.append(roots);
680
681     if (Options::logGC() == GCLogging::Verbose)
682         dataLog("Conservative Roots:\n", m_slotVisitor);
683
684     m_slotVisitor.donateAndDrain();
685 }
686
687 void Heap::visitCompilerWorklistWeakReferences()
688 {
689 #if ENABLE(DFG_JIT)
690     for (auto worklist : m_suspendedCompilerWorklists)
691         worklist->visitWeakReferences(m_slotVisitor);
692
693     if (Options::logGC() == GCLogging::Verbose)
694         dataLog("DFG Worklists:\n", m_slotVisitor);
695 #endif
696 }
697
698 void Heap::removeDeadCompilerWorklistEntries()
699 {
700 #if ENABLE(DFG_JIT)
701     GCPHASE(FinalizeDFGWorklists);
702     for (auto worklist : m_suspendedCompilerWorklists)
703         worklist->removeDeadPlans(*m_vm);
704 #endif
705 }
706
707 bool Heap::isHeapSnapshotting() const
708 {
709     HeapProfiler* heapProfiler = m_vm->heapProfiler();
710     if (UNLIKELY(heapProfiler))
711         return heapProfiler->activeSnapshotBuilder();
712     return false;
713 }
714
715 struct GatherHeapSnapshotData : MarkedBlock::CountFunctor {
716     GatherHeapSnapshotData(HeapSnapshotBuilder& builder)
717         : m_builder(builder)
718     {
719     }
720
721     IterationStatus operator()(HeapCell* heapCell, HeapCell::Kind kind) const
722     {
723         if (kind == HeapCell::JSCell) {
724             JSCell* cell = static_cast<JSCell*>(heapCell);
725             cell->methodTable()->heapSnapshot(cell, m_builder);
726         }
727         return IterationStatus::Continue;
728     }
729
730     HeapSnapshotBuilder& m_builder;
731 };
732
733 void Heap::gatherExtraHeapSnapshotData(HeapProfiler& heapProfiler)
734 {
735     GCPHASE(GatherExtraHeapSnapshotData);
736     if (HeapSnapshotBuilder* builder = heapProfiler.activeSnapshotBuilder()) {
737         HeapIterationScope heapIterationScope(*this);
738         GatherHeapSnapshotData functor(*builder);
739         m_objectSpace.forEachLiveCell(heapIterationScope, functor);
740     }
741 }
742
743 struct RemoveDeadHeapSnapshotNodes : MarkedBlock::CountFunctor {
744     RemoveDeadHeapSnapshotNodes(HeapSnapshot& snapshot)
745         : m_snapshot(snapshot)
746     {
747     }
748
749     IterationStatus operator()(HeapCell* cell, HeapCell::Kind kind) const
750     {
751         if (kind == HeapCell::JSCell)
752             m_snapshot.sweepCell(static_cast<JSCell*>(cell));
753         return IterationStatus::Continue;
754     }
755
756     HeapSnapshot& m_snapshot;
757 };
758
759 void Heap::removeDeadHeapSnapshotNodes(HeapProfiler& heapProfiler)
760 {
761     GCPHASE(RemoveDeadHeapSnapshotNodes);
762     if (HeapSnapshot* snapshot = heapProfiler.mostRecentSnapshot()) {
763         HeapIterationScope heapIterationScope(*this);
764         RemoveDeadHeapSnapshotNodes functor(*snapshot);
765         m_objectSpace.forEachDeadCell(heapIterationScope, functor);
766         snapshot->shrinkToFit();
767     }
768 }
769
770 void Heap::visitProtectedObjects(HeapRootVisitor& heapRootVisitor)
771 {
772     GCPHASE(VisitProtectedObjects);
773
774     for (auto& pair : m_protectedValues)
775         heapRootVisitor.visit(&pair.key);
776
777     if (Options::logGC() == GCLogging::Verbose)
778         dataLog("Protected Objects:\n", m_slotVisitor);
779
780     m_slotVisitor.donateAndDrain();
781 }
782
783 void Heap::visitArgumentBuffers(HeapRootVisitor& visitor)
784 {
785     GCPHASE(MarkingArgumentBuffers);
786     if (!m_markListSet || !m_markListSet->size())
787         return;
788
789     MarkedArgumentBuffer::markLists(visitor, *m_markListSet);
790
791     if (Options::logGC() == GCLogging::Verbose)
792         dataLog("Argument Buffers:\n", m_slotVisitor);
793
794     m_slotVisitor.donateAndDrain();
795 }
796
797 void Heap::visitException(HeapRootVisitor& visitor)
798 {
799     GCPHASE(MarkingException);
800     if (!m_vm->exception() && !m_vm->lastException())
801         return;
802
803     visitor.visit(m_vm->addressOfException());
804     visitor.visit(m_vm->addressOfLastException());
805
806     if (Options::logGC() == GCLogging::Verbose)
807         dataLog("Exceptions:\n", m_slotVisitor);
808
809     m_slotVisitor.donateAndDrain();
810 }
811
812 void Heap::visitStrongHandles(HeapRootVisitor& visitor)
813 {
814     GCPHASE(VisitStrongHandles);
815     m_handleSet.visitStrongHandles(visitor);
816
817     if (Options::logGC() == GCLogging::Verbose)
818         dataLog("Strong Handles:\n", m_slotVisitor);
819
820     m_slotVisitor.donateAndDrain();
821 }
822
823 void Heap::visitHandleStack(HeapRootVisitor& visitor)
824 {
825     GCPHASE(VisitHandleStack);
826     m_handleStack.visit(visitor);
827
828     if (Options::logGC() == GCLogging::Verbose)
829         dataLog("Handle Stack:\n", m_slotVisitor);
830
831     m_slotVisitor.donateAndDrain();
832 }
833
834 void Heap::visitSamplingProfiler()
835 {
836 #if ENABLE(SAMPLING_PROFILER)
837     if (SamplingProfiler* samplingProfiler = m_vm->samplingProfiler()) {
838         ASSERT(samplingProfiler->getLock().isLocked());
839         GCPHASE(VisitSamplingProfiler);
840         samplingProfiler->visit(m_slotVisitor);
841         if (Options::logGC() == GCLogging::Verbose)
842             dataLog("Sampling Profiler data:\n", m_slotVisitor);
843
844         m_slotVisitor.donateAndDrain();
845         samplingProfiler->getLock().unlock();
846     }
847 #endif // ENABLE(SAMPLING_PROFILER)
848 }
849
850 void Heap::visitShadowChicken()
851 {
852     m_vm->shadowChicken().visitChildren(m_slotVisitor);
853 }
854
855 void Heap::traceCodeBlocksAndJITStubRoutines()
856 {
857     GCPHASE(TraceCodeBlocksAndJITStubRoutines);
858     m_jitStubRoutines.traceMarkedStubRoutines(m_slotVisitor);
859
860     if (Options::logGC() == GCLogging::Verbose)
861         dataLog("Code Blocks and JIT Stub Routines:\n", m_slotVisitor);
862
863     m_slotVisitor.donateAndDrain();
864 }
865
866 void Heap::converge()
867 {
868     GCPHASE(Convergence);
869     m_slotVisitor.drainFromShared(SlotVisitor::MasterDrain);
870 }
871
872 void Heap::visitWeakHandles(HeapRootVisitor& visitor)
873 {
874     GCPHASE(VisitingLiveWeakHandles);
875     while (true) {
876         m_objectSpace.visitWeakSets(visitor);
877         harvestWeakReferences();
878         visitCompilerWorklistWeakReferences();
879         if (m_slotVisitor.isEmpty())
880             break;
881
882         if (Options::logGC() == GCLogging::Verbose)
883             dataLog("Live Weak Handles:\n", m_slotVisitor);
884
885         {
886             ParallelModeEnabler enabler(m_slotVisitor);
887             m_slotVisitor.donateAndDrain();
888             m_slotVisitor.drainFromShared(SlotVisitor::MasterDrain);
889         }
890     }
891 }
892
893 void Heap::updateObjectCounts(double gcStartTime)
894 {
895     GCCOUNTER(VisitedValueCount, m_slotVisitor.visitCount() + threadVisitCount());
896
897     if (Options::logGC() == GCLogging::Verbose) {
898         size_t visitCount = m_slotVisitor.visitCount();
899         visitCount += threadVisitCount();
900         dataLogF("\nNumber of live Objects after GC %lu, took %.6f secs\n", static_cast<unsigned long>(visitCount), WTF::monotonicallyIncreasingTime() - gcStartTime);
901     }
902     
903     size_t bytesRemovedFromOldSpaceDueToReallocation =
904         m_storageSpace.takeBytesRemovedFromOldSpaceDueToReallocation();
905     
906     if (m_operationInProgress == FullCollection) {
907         m_totalBytesVisited = 0;
908         m_totalBytesCopied = 0;
909     } else
910         m_totalBytesCopied -= bytesRemovedFromOldSpaceDueToReallocation;
911
912     m_totalBytesVisitedThisCycle = m_slotVisitor.bytesVisited() + threadBytesVisited();
913     m_totalBytesCopiedThisCycle = m_slotVisitor.bytesCopied() + threadBytesCopied();
914     
915     m_totalBytesVisited += m_totalBytesVisitedThisCycle;
916     m_totalBytesCopied += m_totalBytesCopiedThisCycle;
917 }
918
919 void Heap::resetVisitors()
920 {
921     m_slotVisitor.reset();
922
923     for (auto& parallelVisitor : m_parallelSlotVisitors)
924         parallelVisitor->reset();
925
926     ASSERT(m_sharedMarkStack.isEmpty());
927     m_weakReferenceHarvesters.removeAll();
928 }
929
930 size_t Heap::objectCount()
931 {
932     return m_objectSpace.objectCount();
933 }
934
935 size_t Heap::extraMemorySize()
936 {
937     return m_extraMemorySize + m_deprecatedExtraMemorySize + m_arrayBuffers.size();
938 }
939
940 size_t Heap::size()
941 {
942     return m_objectSpace.size() + m_storageSpace.size() + extraMemorySize();
943 }
944
945 size_t Heap::capacity()
946 {
947     return m_objectSpace.capacity() + m_storageSpace.capacity() + extraMemorySize();
948 }
949
950 size_t Heap::protectedGlobalObjectCount()
951 {
952     size_t result = 0;
953     forEachProtectedCell(
954         [&] (JSCell* cell) {
955             if (cell->isObject() && asObject(cell)->isGlobalObject())
956                 result++;
957         });
958     return result;
959 }
960
961 size_t Heap::globalObjectCount()
962 {
963     HeapIterationScope iterationScope(*this);
964     size_t result = 0;
965     m_objectSpace.forEachLiveCell(
966         iterationScope,
967         [&] (HeapCell* heapCell, HeapCell::Kind kind) -> IterationStatus {
968             if (kind != HeapCell::JSCell)
969                 return IterationStatus::Continue;
970             JSCell* cell = static_cast<JSCell*>(heapCell);
971             if (cell->isObject() && asObject(cell)->isGlobalObject())
972                 result++;
973             return IterationStatus::Continue;
974         });
975     return result;
976 }
977
978 size_t Heap::protectedObjectCount()
979 {
980     size_t result = 0;
981     forEachProtectedCell(
982         [&] (JSCell*) {
983             result++;
984         });
985     return result;
986 }
987
988 std::unique_ptr<TypeCountSet> Heap::protectedObjectTypeCounts()
989 {
990     std::unique_ptr<TypeCountSet> result = std::make_unique<TypeCountSet>();
991     forEachProtectedCell(
992         [&] (JSCell* cell) {
993             recordType(*result, cell);
994         });
995     return result;
996 }
997
998 std::unique_ptr<TypeCountSet> Heap::objectTypeCounts()
999 {
1000     std::unique_ptr<TypeCountSet> result = std::make_unique<TypeCountSet>();
1001     HeapIterationScope iterationScope(*this);
1002     m_objectSpace.forEachLiveCell(
1003         iterationScope,
1004         [&] (HeapCell* cell, HeapCell::Kind kind) -> IterationStatus {
1005             if (kind == HeapCell::JSCell)
1006                 recordType(*result, static_cast<JSCell*>(cell));
1007             return IterationStatus::Continue;
1008         });
1009     return result;
1010 }
1011
1012 void Heap::deleteAllCodeBlocks()
1013 {
1014     // If JavaScript is running, it's not safe to delete all JavaScript code, since
1015     // we'll end up returning to deleted code.
1016     RELEASE_ASSERT(!m_vm->entryScope);
1017     ASSERT(m_operationInProgress == NoOperation);
1018
1019     completeAllJITPlans();
1020
1021     for (ExecutableBase* executable : m_executables)
1022         executable->clearCode();
1023 }
1024
1025 void Heap::deleteAllUnlinkedCodeBlocks()
1026 {
1027     for (ExecutableBase* current : m_executables) {
1028         if (!current->isFunctionExecutable())
1029             continue;
1030         static_cast<FunctionExecutable*>(current)->unlinkedExecutable()->clearCode();
1031     }
1032 }
1033
1034 void Heap::clearUnmarkedExecutables()
1035 {
1036     GCPHASE(ClearUnmarkedExecutables);
1037     for (unsigned i = m_executables.size(); i--;) {
1038         ExecutableBase* current = m_executables[i];
1039         if (isMarked(current))
1040             continue;
1041
1042         // Eagerly dereference the Executable's JITCode in order to run watchpoint
1043         // destructors. Otherwise, watchpoints might fire for deleted CodeBlocks.
1044         current->clearCode();
1045         std::swap(m_executables[i], m_executables.last());
1046         m_executables.removeLast();
1047     }
1048
1049     m_executables.shrinkToFit();
1050 }
1051
1052 void Heap::deleteUnmarkedCompiledCode()
1053 {
1054     GCPHASE(DeleteCodeBlocks);
1055     clearUnmarkedExecutables();
1056     m_codeBlocks.deleteUnmarkedAndUnreferenced(m_operationInProgress);
1057     m_jitStubRoutines.deleteUnmarkedJettisonedStubRoutines();
1058 }
1059
1060 void Heap::addToRememberedSet(const JSCell* cell)
1061 {
1062     ASSERT(cell);
1063     ASSERT(!Options::useConcurrentJIT() || !isCompilationThread());
1064     ASSERT(cell->cellState() == CellState::OldBlack);
1065     // Indicate that this object is grey and that it's one of the following:
1066     // - A re-greyed object during a concurrent collection.
1067     // - An old remembered object.
1068     // "OldGrey" doesn't tell us which of these things is true, but we usually treat the two cases the
1069     // same.
1070     cell->setCellState(CellState::OldGrey);
1071     m_slotVisitor.appendToMarkStack(const_cast<JSCell*>(cell));
1072 }
1073
1074 void Heap::collectAllGarbage()
1075 {
1076     if (!m_isSafeToCollect)
1077         return;
1078
1079     collect(FullCollection);
1080
1081     DeferGCForAWhile deferGC(*this);
1082     if (UNLIKELY(Options::useImmortalObjects()))
1083         sweeper()->willFinishSweeping();
1084     else {
1085         m_objectSpace.sweep();
1086         m_objectSpace.shrink();
1087     }
1088     ASSERT(m_blockSnapshot.isEmpty());
1089
1090     sweepAllLogicallyEmptyWeakBlocks();
1091 }
1092
1093 NEVER_INLINE void Heap::collect(HeapOperation collectionType)
1094 {
1095     void* stackTop;
1096     ALLOCATE_AND_GET_REGISTER_STATE(registers);
1097
1098     collectImpl(collectionType, wtfThreadData().stack().origin(), &stackTop, registers);
1099
1100     sanitizeStackForVM(m_vm);
1101 }
1102
1103 NEVER_INLINE void Heap::collectImpl(HeapOperation collectionType, void* stackOrigin, void* stackTop, MachineThreads::RegisterState& calleeSavedRegisters)
1104 {
1105 #if ENABLE(ALLOCATION_LOGGING)
1106     dataLogF("JSC GC starting collection.\n");
1107 #endif
1108     
1109     double before = 0;
1110     if (Options::logGC()) {
1111         dataLog("[GC: ", capacity() / 1024, " kb ");
1112         before = currentTimeMS();
1113     }
1114     
1115     if (vm()->typeProfiler()) {
1116         DeferGCForAWhile awhile(*this);
1117         vm()->typeProfilerLog()->processLogEntries(ASCIILiteral("GC"));
1118     }
1119
1120 #if ENABLE(JIT)
1121     {
1122         DeferGCForAWhile awhile(*this);
1123         JITWorklist::instance()->completeAllForVM(*m_vm);
1124     }
1125 #endif // ENABLE(JIT)
1126
1127     vm()->shadowChicken().update(*vm(), vm()->topCallFrame);
1128
1129     RELEASE_ASSERT(!m_deferralDepth);
1130     ASSERT(vm()->currentThreadIsHoldingAPILock());
1131     RELEASE_ASSERT(vm()->atomicStringTable() == wtfThreadData().atomicStringTable());
1132     ASSERT(m_isSafeToCollect);
1133     RELEASE_ASSERT(m_operationInProgress == NoOperation);
1134
1135     suspendCompilerThreads();
1136     willStartCollection(collectionType);
1137     GCPHASE(Collect);
1138
1139     double gcStartTime = WTF::monotonicallyIncreasingTime();
1140     if (m_verifier) {
1141         // Verify that live objects from the last GC cycle haven't been corrupted by
1142         // mutators before we begin this new GC cycle.
1143         m_verifier->verify(HeapVerifier::Phase::BeforeGC);
1144
1145         m_verifier->initializeGCCycle();
1146         m_verifier->gatherLiveObjects(HeapVerifier::Phase::BeforeMarking);
1147     }
1148
1149     flushOldStructureIDTables();
1150     stopAllocation();
1151     flushWriteBarrierBuffer();
1152
1153     markRoots(gcStartTime, stackOrigin, stackTop, calleeSavedRegisters);
1154
1155     if (m_verifier) {
1156         m_verifier->gatherLiveObjects(HeapVerifier::Phase::AfterMarking);
1157         m_verifier->verify(HeapVerifier::Phase::AfterMarking);
1158     }
1159
1160     if (vm()->typeProfiler())
1161         vm()->typeProfiler()->invalidateTypeSetCache();
1162
1163     reapWeakHandles();
1164     pruneStaleEntriesFromWeakGCMaps();
1165     sweepArrayBuffers();
1166     snapshotMarkedSpace();
1167
1168     copyBackingStores();
1169
1170     finalizeUnconditionalFinalizers();
1171     removeDeadCompilerWorklistEntries();
1172     deleteUnmarkedCompiledCode();
1173     deleteSourceProviderCaches();
1174
1175     notifyIncrementalSweeper();
1176     writeBarrierCurrentlyExecutingCodeBlocks();
1177
1178     resetAllocators();
1179     updateAllocationLimits();
1180     didFinishCollection(gcStartTime);
1181     resumeCompilerThreads();
1182
1183     if (m_verifier) {
1184         m_verifier->trimDeadObjects();
1185         m_verifier->verify(HeapVerifier::Phase::AfterGC);
1186     }
1187
1188     if (Options::logGC()) {
1189         double after = currentTimeMS();
1190         dataLog(after - before, " ms]\n");
1191     }
1192 }
1193
1194 void Heap::suspendCompilerThreads()
1195 {
1196 #if ENABLE(DFG_JIT)
1197     GCPHASE(SuspendCompilerThreads);
1198     ASSERT(m_suspendedCompilerWorklists.isEmpty());
1199     for (unsigned i = DFG::numberOfWorklists(); i--;) {
1200         if (DFG::Worklist* worklist = DFG::worklistForIndexOrNull(i)) {
1201             m_suspendedCompilerWorklists.append(worklist);
1202             worklist->suspendAllThreads();
1203         }
1204     }
1205 #endif
1206 }
1207
1208 void Heap::willStartCollection(HeapOperation collectionType)
1209 {
1210     GCPHASE(StartingCollection);
1211     
1212     if (Options::logGC())
1213         dataLog("=> ");
1214     
1215     if (shouldDoFullCollection(collectionType)) {
1216         m_operationInProgress = FullCollection;
1217         m_shouldDoFullCollection = false;
1218         if (Options::logGC())
1219             dataLog("FullCollection, ");
1220     } else {
1221         m_operationInProgress = EdenCollection;
1222         if (Options::logGC())
1223             dataLog("EdenCollection, ");
1224     }
1225     if (m_operationInProgress == FullCollection) {
1226         m_sizeBeforeLastFullCollect = m_sizeAfterLastCollect + m_bytesAllocatedThisCycle;
1227         m_extraMemorySize = 0;
1228         m_deprecatedExtraMemorySize = 0;
1229 #if ENABLE(RESOURCE_USAGE)
1230         m_externalMemorySize = 0;
1231 #endif
1232
1233         if (m_fullActivityCallback)
1234             m_fullActivityCallback->willCollect();
1235     } else {
1236         ASSERT(m_operationInProgress == EdenCollection);
1237         m_sizeBeforeLastEdenCollect = m_sizeAfterLastCollect + m_bytesAllocatedThisCycle;
1238     }
1239
1240     if (m_edenActivityCallback)
1241         m_edenActivityCallback->willCollect();
1242
1243     for (auto* observer : m_observers)
1244         observer->willGarbageCollect();
1245 }
1246
1247 void Heap::flushOldStructureIDTables()
1248 {
1249     GCPHASE(FlushOldStructureIDTables);
1250     m_structureIDTable.flushOldTables();
1251 }
1252
1253 void Heap::flushWriteBarrierBuffer()
1254 {
1255     GCPHASE(FlushWriteBarrierBuffer);
1256     if (m_operationInProgress == EdenCollection) {
1257         m_writeBarrierBuffer.flush(*this);
1258         return;
1259     }
1260     m_writeBarrierBuffer.reset();
1261 }
1262
1263 void Heap::stopAllocation()
1264 {
1265     GCPHASE(StopAllocation);
1266     m_objectSpace.stopAllocating();
1267     if (m_operationInProgress == FullCollection)
1268         m_storageSpace.didStartFullCollection();
1269 }
1270
1271 void Heap::reapWeakHandles()
1272 {
1273     GCPHASE(ReapingWeakHandles);
1274     m_objectSpace.reapWeakSets();
1275 }
1276
1277 void Heap::pruneStaleEntriesFromWeakGCMaps()
1278 {
1279     GCPHASE(PruningStaleEntriesFromWeakGCMaps);
1280     if (m_operationInProgress != FullCollection)
1281         return;
1282     for (auto& pruneCallback : m_weakGCMaps.values())
1283         pruneCallback();
1284 }
1285
1286 void Heap::sweepArrayBuffers()
1287 {
1288     GCPHASE(SweepingArrayBuffers);
1289     m_arrayBuffers.sweep();
1290 }
1291
1292 struct MarkedBlockSnapshotFunctor : public MarkedBlock::VoidFunctor {
1293     MarkedBlockSnapshotFunctor(Vector<MarkedBlock*>& blocks) 
1294         : m_index(0) 
1295         , m_blocks(blocks)
1296     {
1297     }
1298
1299     void operator()(MarkedBlock* block) const { m_blocks[m_index++] = block; }
1300
1301     // FIXME: This is a mutable field becaue this isn't a C++ lambda.
1302     // https://bugs.webkit.org/show_bug.cgi?id=159644
1303     mutable size_t m_index;
1304     Vector<MarkedBlock*>& m_blocks;
1305 };
1306
1307 void Heap::snapshotMarkedSpace()
1308 {
1309     GCPHASE(SnapshotMarkedSpace);
1310
1311     if (m_operationInProgress == EdenCollection) {
1312         m_blockSnapshot.appendVector(m_objectSpace.blocksWithNewObjects());
1313         // Sort and deduplicate the block snapshot since we might be appending to an unfinished work list.
1314         std::sort(m_blockSnapshot.begin(), m_blockSnapshot.end());
1315         m_blockSnapshot.shrink(std::unique(m_blockSnapshot.begin(), m_blockSnapshot.end()) - m_blockSnapshot.begin());
1316     } else {
1317         m_blockSnapshot.resizeToFit(m_objectSpace.blocks().set().size());
1318         MarkedBlockSnapshotFunctor functor(m_blockSnapshot);
1319         m_objectSpace.forEachBlock(functor);
1320     }
1321 }
1322
1323 void Heap::deleteSourceProviderCaches()
1324 {
1325     GCPHASE(DeleteSourceProviderCaches);
1326     m_vm->clearSourceProviderCaches();
1327 }
1328
1329 void Heap::notifyIncrementalSweeper()
1330 {
1331     GCPHASE(NotifyIncrementalSweeper);
1332
1333     if (m_operationInProgress == FullCollection) {
1334         if (!m_logicallyEmptyWeakBlocks.isEmpty())
1335             m_indexOfNextLogicallyEmptyWeakBlockToSweep = 0;
1336     }
1337
1338     m_sweeper->startSweeping();
1339 }
1340
1341 void Heap::writeBarrierCurrentlyExecutingCodeBlocks()
1342 {
1343     GCPHASE(WriteBarrierCurrentlyExecutingCodeBlocks);
1344     m_codeBlocks.writeBarrierCurrentlyExecutingCodeBlocks(this);
1345 }
1346
1347 void Heap::resetAllocators()
1348 {
1349     GCPHASE(ResetAllocators);
1350     m_objectSpace.resetAllocators();
1351 }
1352
1353 void Heap::updateAllocationLimits()
1354 {
1355     GCPHASE(UpdateAllocationLimits);
1356     
1357     // Calculate our current heap size threshold for the purpose of figuring out when we should
1358     // run another collection. This isn't the same as either size() or capacity(), though it should
1359     // be somewhere between the two. The key is to match the size calculations involved calls to
1360     // didAllocate(), while never dangerously underestimating capacity(). In extreme cases of
1361     // fragmentation, we may have size() much smaller than capacity(). Our collector sometimes
1362     // temporarily allows very high fragmentation because it doesn't defragment old blocks in copied
1363     // space.
1364     size_t currentHeapSize = 0;
1365
1366     // For marked space, we use the total number of bytes visited. This matches the logic for
1367     // MarkedAllocator's calls to didAllocate(), which effectively accounts for the total size of
1368     // objects allocated rather than blocks used. This will underestimate capacity(), and in case
1369     // of fragmentation, this may be substantial. Fortunately, marked space rarely fragments because
1370     // cells usually have a narrow range of sizes. So, the underestimation is probably OK.
1371     currentHeapSize += m_totalBytesVisited;
1372
1373     // For copied space, we use the capacity of storage space. This is because copied space may get
1374     // badly fragmented between full collections. This arises when each eden collection evacuates
1375     // much less than one CopiedBlock's worth of stuff. It can also happen when CopiedBlocks get
1376     // pinned due to very short-lived objects. In such a case, we want to get to a full collection
1377     // sooner rather than later. If we used m_totalBytesCopied, then for for each CopiedBlock that an
1378     // eden allocation promoted, we would only deduct the one object's size from eden size. This
1379     // would mean that we could "leak" many CopiedBlocks before we did a full collection and
1380     // defragmented all of them. It would be great to use m_totalBytesCopied, but we'd need to
1381     // augment it with something that accounts for those fragmented blocks.
1382     // FIXME: Make it possible to compute heap size using m_totalBytesCopied rather than
1383     // m_storageSpace.capacity()
1384     // https://bugs.webkit.org/show_bug.cgi?id=150268
1385     ASSERT(m_totalBytesCopied <= m_storageSpace.size());
1386     currentHeapSize += m_storageSpace.capacity();
1387
1388     // It's up to the user to ensure that extraMemorySize() ends up corresponding to allocation-time
1389     // extra memory reporting.
1390     currentHeapSize += extraMemorySize();
1391     
1392     if (Options::gcMaxHeapSize() && currentHeapSize > Options::gcMaxHeapSize())
1393         HeapStatistics::exitWithFailure();
1394
1395     if (m_operationInProgress == FullCollection) {
1396         // To avoid pathological GC churn in very small and very large heaps, we set
1397         // the new allocation limit based on the current size of the heap, with a
1398         // fixed minimum.
1399         m_maxHeapSize = max(minHeapSize(m_heapType, m_ramSize), proportionalHeapSize(currentHeapSize, m_ramSize));
1400         m_maxEdenSize = m_maxHeapSize - currentHeapSize;
1401         m_sizeAfterLastFullCollect = currentHeapSize;
1402         m_bytesAbandonedSinceLastFullCollect = 0;
1403     } else {
1404         static const bool verbose = false;
1405         
1406         ASSERT(currentHeapSize >= m_sizeAfterLastCollect);
1407         m_maxEdenSize = m_maxHeapSize - currentHeapSize;
1408         m_sizeAfterLastEdenCollect = currentHeapSize;
1409         if (verbose) {
1410             dataLog("Max heap size: ", m_maxHeapSize, "\n");
1411             dataLog("Current heap size: ", currentHeapSize, "\n");
1412             dataLog("Size after last eden collection: ", m_sizeAfterLastEdenCollect, "\n");
1413         }
1414         double edenToOldGenerationRatio = (double)m_maxEdenSize / (double)m_maxHeapSize;
1415         if (verbose)
1416             dataLog("Eden to old generation ratio: ", edenToOldGenerationRatio, "\n");
1417         double minEdenToOldGenerationRatio = 1.0 / 3.0;
1418         if (edenToOldGenerationRatio < minEdenToOldGenerationRatio)
1419             m_shouldDoFullCollection = true;
1420         // This seems suspect at first, but what it does is ensure that the nursery size is fixed.
1421         m_maxHeapSize += currentHeapSize - m_sizeAfterLastCollect;
1422         m_maxEdenSize = m_maxHeapSize - currentHeapSize;
1423         if (m_fullActivityCallback) {
1424             ASSERT(currentHeapSize >= m_sizeAfterLastFullCollect);
1425             m_fullActivityCallback->didAllocate(currentHeapSize - m_sizeAfterLastFullCollect);
1426         }
1427     }
1428
1429     m_sizeAfterLastCollect = currentHeapSize;
1430     m_bytesAllocatedThisCycle = 0;
1431
1432     if (Options::logGC())
1433         dataLog(currentHeapSize / 1024, " kb, ");
1434 }
1435
1436 void Heap::didFinishCollection(double gcStartTime)
1437 {
1438     GCPHASE(FinishingCollection);
1439     double gcEndTime = WTF::monotonicallyIncreasingTime();
1440     HeapOperation operation = m_operationInProgress;
1441     if (m_operationInProgress == FullCollection)
1442         m_lastFullGCLength = gcEndTime - gcStartTime;
1443     else
1444         m_lastEdenGCLength = gcEndTime - gcStartTime;
1445
1446 #if ENABLE(RESOURCE_USAGE)
1447     ASSERT(externalMemorySize() <= extraMemorySize());
1448 #endif
1449
1450     if (Options::recordGCPauseTimes())
1451         HeapStatistics::recordGCPauseTime(gcStartTime, gcEndTime);
1452
1453     if (Options::useZombieMode())
1454         zombifyDeadObjects();
1455
1456     if (Options::dumpObjectStatistics())
1457         HeapStatistics::dumpObjectStatistics(this);
1458
1459     if (HeapProfiler* heapProfiler = m_vm->heapProfiler()) {
1460         gatherExtraHeapSnapshotData(*heapProfiler);
1461         removeDeadHeapSnapshotNodes(*heapProfiler);
1462     }
1463
1464     RELEASE_ASSERT(m_operationInProgress == EdenCollection || m_operationInProgress == FullCollection);
1465     m_operationInProgress = NoOperation;
1466
1467     for (auto* observer : m_observers)
1468         observer->didGarbageCollect(operation);
1469 }
1470
1471 void Heap::resumeCompilerThreads()
1472 {
1473 #if ENABLE(DFG_JIT)
1474     GCPHASE(ResumeCompilerThreads);
1475     for (auto worklist : m_suspendedCompilerWorklists)
1476         worklist->resumeAllThreads();
1477     m_suspendedCompilerWorklists.clear();
1478 #endif
1479 }
1480
1481 void Heap::setFullActivityCallback(PassRefPtr<FullGCActivityCallback> activityCallback)
1482 {
1483     m_fullActivityCallback = activityCallback;
1484 }
1485
1486 void Heap::setEdenActivityCallback(PassRefPtr<EdenGCActivityCallback> activityCallback)
1487 {
1488     m_edenActivityCallback = activityCallback;
1489 }
1490
1491 GCActivityCallback* Heap::fullActivityCallback()
1492 {
1493     return m_fullActivityCallback.get();
1494 }
1495
1496 GCActivityCallback* Heap::edenActivityCallback()
1497 {
1498     return m_edenActivityCallback.get();
1499 }
1500
1501 void Heap::setIncrementalSweeper(std::unique_ptr<IncrementalSweeper> sweeper)
1502 {
1503     m_sweeper = WTFMove(sweeper);
1504 }
1505
1506 IncrementalSweeper* Heap::sweeper()
1507 {
1508     return m_sweeper.get();
1509 }
1510
1511 void Heap::setGarbageCollectionTimerEnabled(bool enable)
1512 {
1513     if (m_fullActivityCallback)
1514         m_fullActivityCallback->setEnabled(enable);
1515     if (m_edenActivityCallback)
1516         m_edenActivityCallback->setEnabled(enable);
1517 }
1518
1519 void Heap::didAllocate(size_t bytes)
1520 {
1521     if (m_edenActivityCallback)
1522         m_edenActivityCallback->didAllocate(m_bytesAllocatedThisCycle + m_bytesAbandonedSinceLastFullCollect);
1523     m_bytesAllocatedThisCycle += bytes;
1524 }
1525
1526 bool Heap::isValidAllocation(size_t)
1527 {
1528     if (!isValidThreadState(m_vm))
1529         return false;
1530
1531     if (m_operationInProgress != NoOperation)
1532         return false;
1533     
1534     return true;
1535 }
1536
1537 void Heap::addFinalizer(JSCell* cell, Finalizer finalizer)
1538 {
1539     WeakSet::allocate(cell, &m_finalizerOwner, reinterpret_cast<void*>(finalizer)); // Balanced by FinalizerOwner::finalize().
1540 }
1541
1542 void Heap::FinalizerOwner::finalize(Handle<Unknown> handle, void* context)
1543 {
1544     HandleSlot slot = handle.slot();
1545     Finalizer finalizer = reinterpret_cast<Finalizer>(context);
1546     finalizer(slot->asCell());
1547     WeakSet::deallocate(WeakImpl::asWeakImpl(slot));
1548 }
1549
1550 void Heap::addExecutable(ExecutableBase* executable)
1551 {
1552     m_executables.append(executable);
1553 }
1554
1555 void Heap::collectAllGarbageIfNotDoneRecently()
1556 {
1557     if (!m_fullActivityCallback) {
1558         collectAllGarbage();
1559         return;
1560     }
1561
1562     if (m_fullActivityCallback->didSyncGCRecently()) {
1563         // A synchronous GC was already requested recently so we merely accelerate next collection.
1564         reportAbandonedObjectGraph();
1565         return;
1566     }
1567
1568     m_fullActivityCallback->setDidSyncGCRecently();
1569     collectAllGarbage();
1570 }
1571
1572 class Zombify : public MarkedBlock::VoidFunctor {
1573 public:
1574     inline void visit(HeapCell* cell) const
1575     {
1576         void** current = reinterpret_cast<void**>(cell);
1577
1578         // We want to maintain zapped-ness because that's how we know if we've called 
1579         // the destructor.
1580         if (cell->isZapped())
1581             current++;
1582
1583         void* limit = static_cast<void*>(reinterpret_cast<char*>(cell) + MarkedBlock::blockFor(cell)->cellSize());
1584         for (; current < limit; current++)
1585             *current = zombifiedBits;
1586     }
1587     IterationStatus operator()(HeapCell* cell, HeapCell::Kind) const
1588     {
1589         visit(cell);
1590         return IterationStatus::Continue;
1591     }
1592 };
1593
1594 void Heap::zombifyDeadObjects()
1595 {
1596     // Sweep now because destructors will crash once we're zombified.
1597     m_objectSpace.zombifySweep();
1598     HeapIterationScope iterationScope(*this);
1599     m_objectSpace.forEachDeadCell(iterationScope, Zombify());
1600 }
1601
1602 void Heap::flushWriteBarrierBuffer(JSCell* cell)
1603 {
1604     m_writeBarrierBuffer.flush(*this);
1605     m_writeBarrierBuffer.add(cell);
1606 }
1607
1608 bool Heap::shouldDoFullCollection(HeapOperation requestedCollectionType) const
1609 {
1610     if (!Options::useGenerationalGC())
1611         return true;
1612
1613     switch (requestedCollectionType) {
1614     case EdenCollection:
1615         return false;
1616     case FullCollection:
1617         return true;
1618     case AnyCollection:
1619         return m_shouldDoFullCollection;
1620     default:
1621         RELEASE_ASSERT_NOT_REACHED();
1622         return false;
1623     }
1624     RELEASE_ASSERT_NOT_REACHED();
1625     return false;
1626 }
1627
1628 void Heap::addLogicallyEmptyWeakBlock(WeakBlock* block)
1629 {
1630     m_logicallyEmptyWeakBlocks.append(block);
1631 }
1632
1633 void Heap::sweepAllLogicallyEmptyWeakBlocks()
1634 {
1635     if (m_logicallyEmptyWeakBlocks.isEmpty())
1636         return;
1637
1638     m_indexOfNextLogicallyEmptyWeakBlockToSweep = 0;
1639     while (sweepNextLogicallyEmptyWeakBlock()) { }
1640 }
1641
1642 bool Heap::sweepNextLogicallyEmptyWeakBlock()
1643 {
1644     if (m_indexOfNextLogicallyEmptyWeakBlockToSweep == WTF::notFound)
1645         return false;
1646
1647     WeakBlock* block = m_logicallyEmptyWeakBlocks[m_indexOfNextLogicallyEmptyWeakBlockToSweep];
1648
1649     block->sweep();
1650     if (block->isEmpty()) {
1651         std::swap(m_logicallyEmptyWeakBlocks[m_indexOfNextLogicallyEmptyWeakBlockToSweep], m_logicallyEmptyWeakBlocks.last());
1652         m_logicallyEmptyWeakBlocks.removeLast();
1653         WeakBlock::destroy(*this, block);
1654     } else
1655         m_indexOfNextLogicallyEmptyWeakBlockToSweep++;
1656
1657     if (m_indexOfNextLogicallyEmptyWeakBlockToSweep >= m_logicallyEmptyWeakBlocks.size()) {
1658         m_indexOfNextLogicallyEmptyWeakBlockToSweep = WTF::notFound;
1659         return false;
1660     }
1661
1662     return true;
1663 }
1664
1665 size_t Heap::threadVisitCount()
1666 {       
1667     unsigned long result = 0;
1668     for (auto& parallelVisitor : m_parallelSlotVisitors)
1669         result += parallelVisitor->visitCount();
1670     return result;
1671 }
1672
1673 size_t Heap::threadBytesVisited()
1674 {       
1675     size_t result = 0;
1676     for (auto& parallelVisitor : m_parallelSlotVisitors)
1677         result += parallelVisitor->bytesVisited();
1678     return result;
1679 }
1680
1681 size_t Heap::threadBytesCopied()
1682 {       
1683     size_t result = 0;
1684     for (auto& parallelVisitor : m_parallelSlotVisitors)
1685         result += parallelVisitor->bytesCopied();
1686     return result;
1687 }
1688
1689 } // namespace JSC