1/*
2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 *     * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *     * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 *     * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include "config.h"
32#include "platform/heap/Heap.h"
33
34#include "platform/ScriptForbiddenScope.h"
35#include "platform/Task.h"
36#include "platform/TraceEvent.h"
37#include "platform/heap/CallbackStack.h"
38#include "platform/heap/ThreadState.h"
39#include "public/platform/Platform.h"
40#include "wtf/AddressSpaceRandomization.h"
41#include "wtf/Assertions.h"
42#include "wtf/LeakAnnotations.h"
43#include "wtf/PassOwnPtr.h"
44#if ENABLE(GC_PROFILE_MARKING)
45#include "wtf/HashMap.h"
46#include "wtf/HashSet.h"
47#include "wtf/text/StringBuilder.h"
48#include "wtf/text/StringHash.h"
49#include <stdio.h>
50#include <utility>
51#endif
52#if ENABLE(GC_PROFILE_HEAP)
53#include "platform/TracedValue.h"
54#endif
55
56#if OS(POSIX)
57#include <sys/mman.h>
58#include <unistd.h>
59#elif OS(WIN)
60#include <windows.h>
61#endif
62
63namespace blink {
64
65#if ENABLE(GC_PROFILE_MARKING)
66static String classOf(const void* object)
67{
68    const GCInfo* gcInfo = Heap::findGCInfo(reinterpret_cast<Address>(const_cast<void*>(object)));
69    if (gcInfo)
70        return gcInfo->m_className;
71
72    return "unknown";
73}
74#endif
75
76static bool vTableInitialized(void* objectPointer)
77{
78    return !!(*reinterpret_cast<Address*>(objectPointer));
79}
80
81#if OS(WIN)
82static bool IsPowerOf2(size_t power)
83{
84    return !((power - 1) & power);
85}
86#endif
87
88static Address roundToBlinkPageBoundary(void* base)
89{
90    return reinterpret_cast<Address>((reinterpret_cast<uintptr_t>(base) + blinkPageOffsetMask) & blinkPageBaseMask);
91}
92
93static size_t roundToOsPageSize(size_t size)
94{
95    return (size + osPageSize() - 1) & ~(osPageSize() - 1);
96}
97
98size_t osPageSize()
99{
100#if OS(POSIX)
101    static const size_t pageSize = getpagesize();
102#else
103    static size_t pageSize = 0;
104    if (!pageSize) {
105        SYSTEM_INFO info;
106        GetSystemInfo(&info);
107        pageSize = info.dwPageSize;
108        ASSERT(IsPowerOf2(pageSize));
109    }
110#endif
111    return pageSize;
112}
113
114class MemoryRegion {
115public:
116    MemoryRegion(Address base, size_t size)
117        : m_base(base)
118        , m_size(size)
119    {
120        ASSERT(size > 0);
121    }
122
123    bool contains(Address addr) const
124    {
125        return m_base <= addr && addr < (m_base + m_size);
126    }
127
128
129    bool contains(const MemoryRegion& other) const
130    {
131        return contains(other.m_base) && contains(other.m_base + other.m_size - 1);
132    }
133
134    void release()
135    {
136#if OS(POSIX)
137        int err = munmap(m_base, m_size);
138        RELEASE_ASSERT(!err);
139#else
140        bool success = VirtualFree(m_base, 0, MEM_RELEASE);
141        RELEASE_ASSERT(success);
142#endif
143    }
144
145    WARN_UNUSED_RETURN bool commit()
146    {
147        ASSERT(Heap::heapDoesNotContainCacheIsEmpty());
148#if OS(POSIX)
149        int err = mprotect(m_base, m_size, PROT_READ | PROT_WRITE);
150        if (!err) {
151            madvise(m_base, m_size, MADV_NORMAL);
152            return true;
153        }
154        return false;
155#else
156        void* result = VirtualAlloc(m_base, m_size, MEM_COMMIT, PAGE_READWRITE);
157        return !!result;
158#endif
159    }
160
161    void decommit()
162    {
163#if OS(POSIX)
164        int err = mprotect(m_base, m_size, PROT_NONE);
165        RELEASE_ASSERT(!err);
166        // FIXME: Consider using MADV_FREE on MacOS.
167        madvise(m_base, m_size, MADV_DONTNEED);
168#else
169        bool success = VirtualFree(m_base, m_size, MEM_DECOMMIT);
170        RELEASE_ASSERT(success);
171#endif
172    }
173
174    Address base() const { return m_base; }
175    size_t size() const { return m_size; }
176
177private:
178    Address m_base;
179    size_t m_size;
180};
181
182// A PageMemoryRegion represents a chunk of reserved virtual address
183// space containing a number of blink heap pages. On Windows, reserved
184// virtual address space can only be given back to the system as a
185// whole. The PageMemoryRegion allows us to do that by keeping track
186// of the number of pages using it in order to be able to release all
187// of the virtual address space when there are no more pages using it.
188class PageMemoryRegion : public MemoryRegion {
189public:
190    ~PageMemoryRegion()
191    {
192        release();
193    }
194
195    void pageRemoved()
196    {
197        if (!--m_numPages)
198            delete this;
199    }
200
201    static PageMemoryRegion* allocate(size_t size, unsigned numPages)
202    {
203        ASSERT(Heap::heapDoesNotContainCacheIsEmpty());
204
205        // Compute a random blink page aligned address for the page memory
206        // region and attempt to get the memory there.
207        Address randomAddress = reinterpret_cast<Address>(WTF::getRandomPageBase());
208        Address alignedRandomAddress = roundToBlinkPageBoundary(randomAddress);
209
210#if OS(POSIX)
211        Address base = static_cast<Address>(mmap(alignedRandomAddress, size, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0));
212        RELEASE_ASSERT(base != MAP_FAILED);
213        if (base == roundToBlinkPageBoundary(base))
214            return new PageMemoryRegion(base, size, numPages);
215
216        // We failed to get a blink page aligned chunk of
217        // memory. Unmap the chunk that we got and fall back to
218        // overallocating and selecting an aligned sub part of what
219        // we allocate.
220        int error = munmap(base, size);
221        RELEASE_ASSERT(!error);
222        size_t allocationSize = size + blinkPageSize;
223        base = static_cast<Address>(mmap(alignedRandomAddress, allocationSize, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0));
224        RELEASE_ASSERT(base != MAP_FAILED);
225
226        Address end = base + allocationSize;
227        Address alignedBase = roundToBlinkPageBoundary(base);
228        Address regionEnd = alignedBase + size;
229
230        // If the allocated memory was not blink page aligned release
231        // the memory before the aligned address.
232        if (alignedBase != base)
233            MemoryRegion(base, alignedBase - base).release();
234
235        // Free the additional memory at the end of the page if any.
236        if (regionEnd < end)
237            MemoryRegion(regionEnd, end - regionEnd).release();
238
239        return new PageMemoryRegion(alignedBase, size, numPages);
240#else
241        Address base = static_cast<Address>(VirtualAlloc(alignedRandomAddress, size, MEM_RESERVE, PAGE_NOACCESS));
242        if (base) {
243            ASSERT(base == alignedRandomAddress);
244            return new PageMemoryRegion(base, size, numPages);
245        }
246
247        // We failed to get the random aligned address that we asked
248        // for. Fall back to overallocating. On Windows it is
249        // impossible to partially release a region of memory
250        // allocated by VirtualAlloc. To avoid wasting virtual address
251        // space we attempt to release a large region of memory
252        // returned as a whole and then allocate an aligned region
253        // inside this larger region.
254        size_t allocationSize = size + blinkPageSize;
255        for (int attempt = 0; attempt < 3; attempt++) {
256            base = static_cast<Address>(VirtualAlloc(0, allocationSize, MEM_RESERVE, PAGE_NOACCESS));
257            RELEASE_ASSERT(base);
258            VirtualFree(base, 0, MEM_RELEASE);
259
260            Address alignedBase = roundToBlinkPageBoundary(base);
261            base = static_cast<Address>(VirtualAlloc(alignedBase, size, MEM_RESERVE, PAGE_NOACCESS));
262            if (base) {
263                ASSERT(base == alignedBase);
264                return new PageMemoryRegion(alignedBase, size, numPages);
265            }
266        }
267
268        // We failed to avoid wasting virtual address space after
269        // several attempts.
270        base = static_cast<Address>(VirtualAlloc(0, allocationSize, MEM_RESERVE, PAGE_NOACCESS));
271        RELEASE_ASSERT(base);
272
273        // FIXME: If base is by accident blink page size aligned
274        // here then we can create two pages out of reserved
275        // space. Do this.
276        Address alignedBase = roundToBlinkPageBoundary(base);
277
278        return new PageMemoryRegion(alignedBase, size, numPages);
279#endif
280    }
281
282private:
283    PageMemoryRegion(Address base, size_t size, unsigned numPages)
284        : MemoryRegion(base, size)
285        , m_numPages(numPages)
286    {
287    }
288
289    unsigned m_numPages;
290};
291
292// Representation of the memory used for a Blink heap page.
293//
294// The representation keeps track of two memory regions:
295//
296// 1. The virtual memory reserved from the system in order to be able
297//    to free all the virtual memory reserved. Multiple PageMemory
298//    instances can share the same reserved memory region and
299//    therefore notify the reserved memory region on destruction so
300//    that the system memory can be given back when all PageMemory
301//    instances for that memory are gone.
302//
303// 2. The writable memory (a sub-region of the reserved virtual
304//    memory region) that is used for the actual heap page payload.
305//
306// Guard pages are created before and after the writable memory.
307class PageMemory {
308public:
309    ~PageMemory()
310    {
311        __lsan_unregister_root_region(m_writable.base(), m_writable.size());
312        m_reserved->pageRemoved();
313    }
314
315    bool commit() WARN_UNUSED_RETURN { return m_writable.commit(); }
316    void decommit() { m_writable.decommit(); }
317
318    Address writableStart() { return m_writable.base(); }
319
320    static PageMemory* setupPageMemoryInRegion(PageMemoryRegion* region, size_t pageOffset, size_t payloadSize)
321    {
322        // Setup the payload one OS page into the page memory. The
323        // first os page is the guard page.
324        Address payloadAddress = region->base() + pageOffset + osPageSize();
325        return new PageMemory(region, MemoryRegion(payloadAddress, payloadSize));
326    }
327
328    // Allocate a virtual address space for one blink page with the
329    // following layout:
330    //
331    //    [ guard os page | ... payload ... | guard os page ]
332    //    ^---{ aligned to blink page size }
333    //
334    static PageMemory* allocate(size_t payloadSize)
335    {
336        ASSERT(payloadSize > 0);
337
338        // Virtual memory allocation routines operate in OS page sizes.
339        // Round up the requested size to nearest os page size.
340        payloadSize = roundToOsPageSize(payloadSize);
341
342        // Overallocate by 2 times OS page size to have space for a
343        // guard page at the beginning and end of blink heap page.
344        size_t allocationSize = payloadSize + 2 * osPageSize();
345        PageMemoryRegion* pageMemoryRegion = PageMemoryRegion::allocate(allocationSize, 1);
346        PageMemory* storage = setupPageMemoryInRegion(pageMemoryRegion, 0, payloadSize);
347        RELEASE_ASSERT(storage->commit());
348        return storage;
349    }
350
351private:
352    PageMemory(PageMemoryRegion* reserved, const MemoryRegion& writable)
353        : m_reserved(reserved)
354        , m_writable(writable)
355    {
356        ASSERT(reserved->contains(writable));
357
358        // Register the writable area of the memory as part of the LSan root set.
359        // Only the writable area is mapped and can contain C++ objects. Those
360        // C++ objects can contain pointers to objects outside of the heap and
361        // should therefore be part of the LSan root set.
362        __lsan_register_root_region(m_writable.base(), m_writable.size());
363    }
364
365
366    PageMemoryRegion* m_reserved;
367    MemoryRegion m_writable;
368};
369
370class GCScope {
371public:
372    explicit GCScope(ThreadState::StackState stackState)
373        : m_state(ThreadState::current())
374        , m_safePointScope(stackState)
375        , m_parkedAllThreads(false)
376    {
377        TRACE_EVENT0("blink_gc", "Heap::GCScope");
378        const char* samplingState = TRACE_EVENT_GET_SAMPLING_STATE();
379        if (m_state->isMainThread())
380            TRACE_EVENT_SET_SAMPLING_STATE("blink_gc", "BlinkGCWaiting");
381
382        m_state->checkThread();
383
384        // FIXME: in an unlikely coincidence that two threads decide
385        // to collect garbage at the same time, avoid doing two GCs in
386        // a row.
387        RELEASE_ASSERT(!m_state->isInGC());
388        RELEASE_ASSERT(!m_state->isSweepInProgress());
389        if (LIKELY(ThreadState::stopThreads())) {
390            m_parkedAllThreads = true;
391            m_state->enterGC();
392        }
393        if (m_state->isMainThread())
394            TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(samplingState);
395    }
396
397    bool allThreadsParked() { return m_parkedAllThreads; }
398
399    ~GCScope()
400    {
401        // Only cleanup if we parked all threads in which case the GC happened
402        // and we need to resume the other threads.
403        if (LIKELY(m_parkedAllThreads)) {
404            m_state->leaveGC();
405            ASSERT(!m_state->isInGC());
406            ThreadState::resumeThreads();
407        }
408    }
409
410private:
411    ThreadState* m_state;
412    ThreadState::SafePointScope m_safePointScope;
413    bool m_parkedAllThreads; // False if we fail to park all threads
414};
415
416NO_SANITIZE_ADDRESS
417bool HeapObjectHeader::isMarked() const
418{
419    checkHeader();
420    unsigned size = asanUnsafeAcquireLoad(&m_size);
421    return size & markBitMask;
422}
423
424NO_SANITIZE_ADDRESS
425void HeapObjectHeader::unmark()
426{
427    checkHeader();
428    m_size &= ~markBitMask;
429}
430
431NO_SANITIZE_ADDRESS
432bool HeapObjectHeader::hasDeadMark() const
433{
434    checkHeader();
435    return m_size & deadBitMask;
436}
437
438NO_SANITIZE_ADDRESS
439void HeapObjectHeader::clearDeadMark()
440{
441    checkHeader();
442    m_size &= ~deadBitMask;
443}
444
445NO_SANITIZE_ADDRESS
446void HeapObjectHeader::setDeadMark()
447{
448    ASSERT(!isMarked());
449    checkHeader();
450    m_size |= deadBitMask;
451}
452
453#if ENABLE(ASSERT)
454NO_SANITIZE_ADDRESS
455void HeapObjectHeader::zapMagic()
456{
457    m_magic = zappedMagic;
458}
459#endif
460
461HeapObjectHeader* HeapObjectHeader::fromPayload(const void* payload)
462{
463    Address addr = reinterpret_cast<Address>(const_cast<void*>(payload));
464    HeapObjectHeader* header =
465        reinterpret_cast<HeapObjectHeader*>(addr - objectHeaderSize);
466    return header;
467}
468
469void HeapObjectHeader::finalize(const GCInfo* gcInfo, Address object, size_t objectSize)
470{
471    ASSERT(gcInfo);
472    if (gcInfo->hasFinalizer()) {
473        gcInfo->m_finalize(object);
474    }
475
476#if ENABLE(ASSERT) || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER)
477    // In Debug builds, memory is zapped when it's freed, and the zapped memory is
478    // zeroed out when the memory is reused. Memory is also zapped when using Leak
479    // Sanitizer because the heap is used as a root region for LSan and therefore
480    // pointers in unreachable memory could hide leaks.
481    for (size_t i = 0; i < objectSize; i++)
482        object[i] = finalizedZapValue;
483
484    // Zap the primary vTable entry (secondary vTable entries are not zapped).
485    if (gcInfo->hasVTable()) {
486        *(reinterpret_cast<uintptr_t*>(object)) = zappedVTable;
487    }
488#endif
489    // In Release builds, the entire object is zeroed out when it is added to the free list.
490    // This happens right after sweeping the page and before the thread commences execution.
491}
492
493NO_SANITIZE_ADDRESS
494void FinalizedHeapObjectHeader::finalize()
495{
496    HeapObjectHeader::finalize(m_gcInfo, payload(), payloadSize());
497}
498
499template<typename Header>
500void LargeHeapObject<Header>::unmark()
501{
502    return heapObjectHeader()->unmark();
503}
504
505template<typename Header>
506bool LargeHeapObject<Header>::isMarked()
507{
508    return heapObjectHeader()->isMarked();
509}
510
511template<typename Header>
512void LargeHeapObject<Header>::setDeadMark()
513{
514    heapObjectHeader()->setDeadMark();
515}
516
517template<typename Header>
518void LargeHeapObject<Header>::checkAndMarkPointer(Visitor* visitor, Address address)
519{
520    ASSERT(contains(address));
521    if (!objectContains(address) || heapObjectHeader()->hasDeadMark())
522        return;
523#if ENABLE(GC_PROFILE_MARKING)
524    visitor->setHostInfo(&address, "stack");
525#endif
526    mark(visitor);
527}
528
529#if ENABLE(ASSERT)
530static bool isUninitializedMemory(void* objectPointer, size_t objectSize)
531{
532    // Scan through the object's fields and check that they are all zero.
533    Address* objectFields = reinterpret_cast<Address*>(objectPointer);
534    for (size_t i = 0; i < objectSize / sizeof(Address); ++i) {
535        if (objectFields[i] != 0)
536            return false;
537    }
538    return true;
539}
540#endif
541
542template<>
543void LargeHeapObject<FinalizedHeapObjectHeader>::mark(Visitor* visitor)
544{
545    if (heapObjectHeader()->hasVTable() && !vTableInitialized(payload())) {
546        FinalizedHeapObjectHeader* header = heapObjectHeader();
547        visitor->markNoTracing(header);
548        ASSERT(isUninitializedMemory(header->payload(), header->payloadSize()));
549    } else {
550        visitor->mark(heapObjectHeader(), heapObjectHeader()->traceCallback());
551    }
552}
553
554template<>
555void LargeHeapObject<HeapObjectHeader>::mark(Visitor* visitor)
556{
557    ASSERT(gcInfo());
558    if (gcInfo()->hasVTable() && !vTableInitialized(payload())) {
559        HeapObjectHeader* header = heapObjectHeader();
560        visitor->markNoTracing(header);
561        ASSERT(isUninitializedMemory(header->payload(), header->payloadSize()));
562    } else {
563        visitor->mark(heapObjectHeader(), gcInfo()->m_trace);
564    }
565}
566
567template<>
568void LargeHeapObject<FinalizedHeapObjectHeader>::finalize()
569{
570    heapObjectHeader()->finalize();
571}
572
573template<>
574void LargeHeapObject<HeapObjectHeader>::finalize()
575{
576    ASSERT(gcInfo());
577    HeapObjectHeader::finalize(gcInfo(), payload(), payloadSize());
578}
579
580FinalizedHeapObjectHeader* FinalizedHeapObjectHeader::fromPayload(const void* payload)
581{
582    Address addr = reinterpret_cast<Address>(const_cast<void*>(payload));
583    FinalizedHeapObjectHeader* header =
584        reinterpret_cast<FinalizedHeapObjectHeader*>(addr - finalizedHeaderSize);
585    return header;
586}
587
588template<typename Header>
589ThreadHeap<Header>::ThreadHeap(ThreadState* state, int index)
590    : m_currentAllocationPoint(0)
591    , m_remainingAllocationSize(0)
592    , m_firstPage(0)
593    , m_firstLargeHeapObject(0)
594    , m_firstPageAllocatedDuringSweeping(0)
595    , m_lastPageAllocatedDuringSweeping(0)
596    , m_mergePoint(0)
597    , m_biggestFreeListIndex(0)
598    , m_threadState(state)
599    , m_index(index)
600    , m_numberOfNormalPages(0)
601    , m_promptlyFreedCount(0)
602{
603    clearFreeLists();
604}
605
606template<typename Header>
607ThreadHeap<Header>::~ThreadHeap()
608{
609    ASSERT(!m_firstPage);
610    ASSERT(!m_firstLargeHeapObject);
611}
612
613template<typename Header>
614void ThreadHeap<Header>::cleanupPages()
615{
616    clearFreeLists();
617    flushHeapContainsCache();
618
619    // Add the ThreadHeap's pages to the orphanedPagePool.
620    for (HeapPage<Header>* page = m_firstPage; page; page = page->m_next)
621        Heap::orphanedPagePool()->addOrphanedPage(m_index, page);
622    m_firstPage = 0;
623
624    for (LargeHeapObject<Header>* largeObject = m_firstLargeHeapObject; largeObject; largeObject = largeObject->m_next)
625        Heap::orphanedPagePool()->addOrphanedPage(m_index, largeObject);
626    m_firstLargeHeapObject = 0;
627}
628
629template<typename Header>
630Address ThreadHeap<Header>::outOfLineAllocate(size_t size, const GCInfo* gcInfo)
631{
632    size_t allocationSize = allocationSizeFromSize(size);
633    if (threadState()->shouldGC()) {
634        if (threadState()->shouldForceConservativeGC())
635            Heap::collectGarbage(ThreadState::HeapPointersOnStack);
636        else
637            threadState()->setGCRequested();
638    }
639    ensureCurrentAllocation(allocationSize, gcInfo);
640    return allocate(size, gcInfo);
641}
642
643template<typename Header>
644bool ThreadHeap<Header>::allocateFromFreeList(size_t minSize)
645{
646    size_t bucketSize = 1 << m_biggestFreeListIndex;
647    int i = m_biggestFreeListIndex;
648    for (; i > 0; i--, bucketSize >>= 1) {
649        if (bucketSize < minSize)
650            break;
651        FreeListEntry* entry = m_freeLists[i];
652        if (entry) {
653            m_biggestFreeListIndex = i;
654            entry->unlink(&m_freeLists[i]);
655            setAllocationPoint(entry->address(), entry->size());
656            ASSERT(currentAllocationPoint() && remainingAllocationSize() >= minSize);
657            return true;
658        }
659    }
660    m_biggestFreeListIndex = i;
661    return false;
662}
663
664template<typename Header>
665void ThreadHeap<Header>::ensureCurrentAllocation(size_t minSize, const GCInfo* gcInfo)
666{
667    ASSERT(minSize >= allocationGranularity);
668    if (remainingAllocationSize() >= minSize)
669        return;
670
671    if (remainingAllocationSize() > 0) {
672        addToFreeList(currentAllocationPoint(), remainingAllocationSize());
673        setAllocationPoint(0, 0);
674    }
675    if (allocateFromFreeList(minSize))
676        return;
677    if (coalesce(minSize) && allocateFromFreeList(minSize))
678        return;
679    addPageToHeap(gcInfo);
680    bool success = allocateFromFreeList(minSize);
681    RELEASE_ASSERT(success);
682}
683
684template<typename Header>
685BaseHeapPage* ThreadHeap<Header>::heapPageFromAddress(Address address)
686{
687    for (HeapPage<Header>* page = m_firstPage; page; page = page->next()) {
688        if (page->contains(address))
689            return page;
690    }
691    for (HeapPage<Header>* page = m_firstPageAllocatedDuringSweeping; page; page = page->next()) {
692        if (page->contains(address))
693            return page;
694    }
695    for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current; current = current->next()) {
696        // Check that large pages are blinkPageSize aligned (modulo the
697        // osPageSize for the guard page).
698        ASSERT(reinterpret_cast<Address>(current) - osPageSize() == roundToBlinkPageStart(reinterpret_cast<Address>(current)));
699        if (current->contains(address))
700            return current;
701    }
702    return 0;
703}
704
705#if ENABLE(GC_PROFILE_MARKING)
706template<typename Header>
707const GCInfo* ThreadHeap<Header>::findGCInfoOfLargeHeapObject(Address address)
708{
709    for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current; current = current->next()) {
710        if (current->contains(address))
711            return current->gcInfo();
712    }
713    return 0;
714}
715#endif
716
717#if ENABLE(GC_PROFILE_HEAP)
718#define GC_PROFILE_HEAP_PAGE_SNAPSHOT_THRESHOLD 0
719template<typename Header>
720void ThreadHeap<Header>::snapshot(TracedValue* json, ThreadState::SnapshotInfo* info)
721{
722    size_t previousPageCount = info->pageCount;
723
724    json->beginArray("pages");
725    for (HeapPage<Header>* page = m_firstPage; page; page = page->next(), ++info->pageCount) {
726        // FIXME: To limit the size of the snapshot we only output "threshold" many page snapshots.
727        if (info->pageCount < GC_PROFILE_HEAP_PAGE_SNAPSHOT_THRESHOLD) {
728            json->beginArray();
729            json->pushInteger(reinterpret_cast<intptr_t>(page));
730            page->snapshot(json, info);
731            json->endArray();
732        } else {
733            page->snapshot(0, info);
734        }
735    }
736    json->endArray();
737
738    json->beginArray("largeObjects");
739    for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current; current = current->next()) {
740        json->beginDictionary();
741        current->snapshot(json, info);
742        json->endDictionary();
743    }
744    json->endArray();
745
746    json->setInteger("pageCount", info->pageCount - previousPageCount);
747}
748#endif
749
750template<typename Header>
751void ThreadHeap<Header>::addToFreeList(Address address, size_t size)
752{
753    ASSERT(heapPageFromAddress(address));
754    ASSERT(heapPageFromAddress(address + size - 1));
755    ASSERT(size < blinkPagePayloadSize());
756    // The free list entries are only pointer aligned (but when we allocate
757    // from them we are 8 byte aligned due to the header size).
758    ASSERT(!((reinterpret_cast<uintptr_t>(address) + sizeof(Header)) & allocationMask));
759    ASSERT(!(size & allocationMask));
760    ASAN_POISON_MEMORY_REGION(address, size);
761    FreeListEntry* entry;
762    if (size < sizeof(*entry)) {
763        // Create a dummy header with only a size and freelist bit set.
764        ASSERT(size >= sizeof(BasicObjectHeader));
765        // Free list encode the size to mark the lost memory as freelist memory.
766        new (NotNull, address) BasicObjectHeader(BasicObjectHeader::freeListEncodedSize(size));
767        // This memory gets lost. Sweeping can reclaim it.
768        return;
769    }
770    entry = new (NotNull, address) FreeListEntry(size);
771#if defined(ADDRESS_SANITIZER)
772    // For ASan we don't add the entry to the free lists until the asanDeferMemoryReuseCount
773    // reaches zero. However we always add entire pages to ensure that adding a new page will
774    // increase the allocation space.
775    if (HeapPage<Header>::payloadSize() != size && !entry->shouldAddToFreeList())
776        return;
777#endif
778    int index = bucketIndexForSize(size);
779    entry->link(&m_freeLists[index]);
780    if (!m_lastFreeListEntries[index])
781        m_lastFreeListEntries[index] = entry;
782    if (index > m_biggestFreeListIndex)
783        m_biggestFreeListIndex = index;
784}
785
786template<typename Header>
787void ThreadHeap<Header>::promptlyFreeObject(Header* header)
788{
789    ASSERT(!m_threadState->isSweepInProgress());
790    header->checkHeader();
791    Address address = reinterpret_cast<Address>(header);
792    Address payload = header->payload();
793    size_t size = header->size();
794    size_t payloadSize = header->payloadSize();
795    BaseHeapPage* page = pageHeaderFromObject(address);
796    ASSERT(size > 0);
797    ASSERT(page == heapPageFromAddress(address));
798
799    {
800        ThreadState::NoSweepScope scope(m_threadState);
801        HeapObjectHeader::finalize(header->gcInfo(), payload, payloadSize);
802#if !ENABLE(ASSERT) && !defined(LEAK_SANITIZER) && !defined(ADDRESS_SANITIZER)
803        memset(payload, 0, payloadSize);
804#endif
805        header->markPromptlyFreed();
806    }
807
808    page->addToPromptlyFreedSize(size);
809    m_promptlyFreedCount++;
810}
811
812template<typename Header>
813bool ThreadHeap<Header>::coalesce(size_t minSize)
814{
815    if (m_threadState->isSweepInProgress())
816        return false;
817
818    if (m_promptlyFreedCount < 256)
819        return false;
820
821    // The smallest bucket able to satisfy an allocation request for minSize is
822    // the bucket where all free-list entries are guarantied to be larger than
823    // minSize. That bucket is one larger than the bucket minSize would go into.
824    size_t neededBucketIndex = bucketIndexForSize(minSize) + 1;
825    size_t neededFreeEntrySize = 1 << neededBucketIndex;
826    size_t neededPromptlyFreedSize = neededFreeEntrySize * 3;
827    size_t foundFreeEntrySize = 0;
828
829    // Bailout early on large requests because it is unlikely we will find a free-list entry.
830    if (neededPromptlyFreedSize >= blinkPageSize)
831        return false;
832
833    TRACE_EVENT_BEGIN2("blink_gc", "ThreadHeap::coalesce" , "requestedSize", (unsigned)minSize , "neededSize", (unsigned)neededFreeEntrySize);
834
835    // Search for a coalescing candidate.
836    ASSERT(!ownsNonEmptyAllocationArea());
837    size_t pageCount = 0;
838    HeapPage<Header>* page = m_firstPage;
839    while (page) {
840        // Only consider one of the first 'n' pages. A "younger" page is more likely to have freed backings.
841        if (++pageCount > numberOfPagesToConsiderForCoalescing) {
842            page = 0;
843            break;
844        }
845        // Only coalesce pages with "sufficient" promptly freed space.
846        if (page->promptlyFreedSize() >= neededPromptlyFreedSize) {
847            break;
848        }
849        page = page->next();
850    }
851
852    // If we found a likely candidate, fully coalesce all its promptly-freed entries.
853    if (page) {
854        page->clearObjectStartBitMap();
855        page->resetPromptlyFreedSize();
856        size_t freedCount = 0;
857        Address startOfGap = page->payload();
858        for (Address headerAddress = startOfGap; headerAddress < page->end(); ) {
859            BasicObjectHeader* basicHeader = reinterpret_cast<BasicObjectHeader*>(headerAddress);
860            ASSERT(basicHeader->size() > 0);
861            ASSERT(basicHeader->size() < blinkPagePayloadSize());
862
863            if (basicHeader->isPromptlyFreed()) {
864                stats().decreaseObjectSpace(reinterpret_cast<Header*>(basicHeader)->payloadSize());
865                size_t size = basicHeader->size();
866                ASSERT(size >= sizeof(Header));
867#if !ENABLE(ASSERT) && !defined(LEAK_SANITIZER) && !defined(ADDRESS_SANITIZER)
868                memset(headerAddress, 0, sizeof(Header));
869#endif
870                ++freedCount;
871                headerAddress += size;
872                continue;
873            }
874
875            if (startOfGap != headerAddress) {
876                size_t size = headerAddress - startOfGap;
877                addToFreeList(startOfGap, size);
878                if (size > foundFreeEntrySize)
879                    foundFreeEntrySize = size;
880            }
881
882            headerAddress += basicHeader->size();
883            startOfGap = headerAddress;
884        }
885
886        if (startOfGap != page->end()) {
887            size_t size = page->end() - startOfGap;
888            addToFreeList(startOfGap, size);
889            if (size > foundFreeEntrySize)
890                foundFreeEntrySize = size;
891        }
892
893        // Check before subtracting because freedCount might not be balanced with freed entries.
894        if (freedCount < m_promptlyFreedCount)
895            m_promptlyFreedCount -= freedCount;
896        else
897            m_promptlyFreedCount = 0;
898    }
899
900    TRACE_EVENT_END1("blink_gc", "ThreadHeap::coalesce", "foundFreeEntrySize", (unsigned)foundFreeEntrySize);
901
902    if (foundFreeEntrySize < neededFreeEntrySize) {
903        // If coalescing failed, reset the freed count to delay coalescing again.
904        m_promptlyFreedCount = 0;
905        return false;
906    }
907
908    return true;
909}
910
911template<typename Header>
912Address ThreadHeap<Header>::allocateLargeObject(size_t size, const GCInfo* gcInfo)
913{
914    // Caller already added space for object header and rounded up to allocation alignment
915    ASSERT(!(size & allocationMask));
916
917    size_t allocationSize = sizeof(LargeHeapObject<Header>) + size;
918
919    // Ensure that there is enough space for alignment. If the header
920    // is not a multiple of 8 bytes we will allocate an extra
921    // headerPadding<Header> bytes to ensure it 8 byte aligned.
922    allocationSize += headerPadding<Header>();
923
924    // If ASan is supported we add allocationGranularity bytes to the allocated space and
925    // poison that to detect overflows
926#if defined(ADDRESS_SANITIZER)
927    allocationSize += allocationGranularity;
928#endif
929    if (threadState()->shouldGC())
930        threadState()->setGCRequested();
931    Heap::flushHeapDoesNotContainCache();
932    PageMemory* pageMemory = PageMemory::allocate(allocationSize);
933    Address largeObjectAddress = pageMemory->writableStart();
934    Address headerAddress = largeObjectAddress + sizeof(LargeHeapObject<Header>) + headerPadding<Header>();
935    memset(headerAddress, 0, size);
936    Header* header = new (NotNull, headerAddress) Header(size, gcInfo);
937    Address result = headerAddress + sizeof(*header);
938    ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask));
939    LargeHeapObject<Header>* largeObject = new (largeObjectAddress) LargeHeapObject<Header>(pageMemory, gcInfo, threadState());
940
941    // Poison the object header and allocationGranularity bytes after the object
942    ASAN_POISON_MEMORY_REGION(header, sizeof(*header));
943    ASAN_POISON_MEMORY_REGION(largeObject->address() + largeObject->size(), allocationGranularity);
944    largeObject->link(&m_firstLargeHeapObject);
945    stats().increaseAllocatedSpace(largeObject->size());
946    stats().increaseObjectSpace(largeObject->payloadSize());
947    return result;
948}
949
950template<typename Header>
951void ThreadHeap<Header>::freeLargeObject(LargeHeapObject<Header>* object, LargeHeapObject<Header>** previousNext)
952{
953    flushHeapContainsCache();
954    object->unlink(previousNext);
955    object->finalize();
956
957    // Unpoison the object header and allocationGranularity bytes after the
958    // object before freeing.
959    ASAN_UNPOISON_MEMORY_REGION(object->heapObjectHeader(), sizeof(Header));
960    ASAN_UNPOISON_MEMORY_REGION(object->address() + object->size(), allocationGranularity);
961
962    if (object->terminating()) {
963        ASSERT(ThreadState::current()->isTerminating());
964        // The thread is shutting down so this object is being removed as part
965        // of a thread local GC. In that case the object could be traced in the
966        // next global GC either due to a dead object being traced via a
967        // conservative pointer or due to a programming error where an object
968        // in another thread heap keeps a dangling pointer to this object.
969        // To guard against this we put the large object memory in the
970        // orphanedPagePool to ensure it is still reachable. After the next global
971        // GC it can be released assuming no rogue/dangling pointers refer to
972        // it.
973        // NOTE: large objects are not moved to the free page pool as it is
974        // unlikely they can be reused due to their individual sizes.
975        Heap::orphanedPagePool()->addOrphanedPage(m_index, object);
976    } else {
977        ASSERT(!ThreadState::current()->isTerminating());
978        PageMemory* memory = object->storage();
979        object->~LargeHeapObject<Header>();
980        delete memory;
981    }
982}
983
984template<typename DataType>
985PagePool<DataType>::PagePool()
986{
987    for (int i = 0; i < NumberOfHeaps; ++i) {
988        m_pool[i] = 0;
989    }
990}
991
992FreePagePool::~FreePagePool()
993{
994    for (int index = 0; index < NumberOfHeaps; ++index) {
995        while (PoolEntry* entry = m_pool[index]) {
996            m_pool[index] = entry->next;
997            PageMemory* memory = entry->data;
998            ASSERT(memory);
999            delete memory;
1000            delete entry;
1001        }
1002    }
1003}
1004
1005void FreePagePool::addFreePage(int index, PageMemory* memory)
1006{
1007    // When adding a page to the pool we decommit it to ensure it is unused
1008    // while in the pool. This also allows the physical memory, backing the
1009    // page, to be given back to the OS.
1010    memory->decommit();
1011    MutexLocker locker(m_mutex[index]);
1012    PoolEntry* entry = new PoolEntry(memory, m_pool[index]);
1013    m_pool[index] = entry;
1014}
1015
1016PageMemory* FreePagePool::takeFreePage(int index)
1017{
1018    MutexLocker locker(m_mutex[index]);
1019    while (PoolEntry* entry = m_pool[index]) {
1020        m_pool[index] = entry->next;
1021        PageMemory* memory = entry->data;
1022        ASSERT(memory);
1023        delete entry;
1024        if (memory->commit())
1025            return memory;
1026
1027        // We got some memory, but failed to commit it, try again.
1028        delete memory;
1029    }
1030    return 0;
1031}
1032
1033OrphanedPagePool::~OrphanedPagePool()
1034{
1035    for (int index = 0; index < NumberOfHeaps; ++index) {
1036        while (PoolEntry* entry = m_pool[index]) {
1037            m_pool[index] = entry->next;
1038            BaseHeapPage* page = entry->data;
1039            delete entry;
1040            PageMemory* memory = page->storage();
1041            ASSERT(memory);
1042            page->~BaseHeapPage();
1043            delete memory;
1044        }
1045    }
1046}
1047
1048void OrphanedPagePool::addOrphanedPage(int index, BaseHeapPage* page)
1049{
1050    page->markOrphaned();
1051    PoolEntry* entry = new PoolEntry(page, m_pool[index]);
1052    m_pool[index] = entry;
1053}
1054
1055NO_SANITIZE_ADDRESS
1056void OrphanedPagePool::decommitOrphanedPages()
1057{
1058#if ENABLE(ASSERT)
1059    // No locking needed as all threads are at safepoints at this point in time.
1060    ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads();
1061    for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it)
1062        ASSERT((*it)->isAtSafePoint());
1063#endif
1064
1065    for (int index = 0; index < NumberOfHeaps; ++index) {
1066        PoolEntry* entry = m_pool[index];
1067        PoolEntry** prevNext = &m_pool[index];
1068        while (entry) {
1069            BaseHeapPage* page = entry->data;
1070            if (page->tracedAfterOrphaned()) {
1071                // If the orphaned page was traced in the last GC it is not
1072                // decommited. We only decommit a page, ie. put it in the
1073                // memory pool, when the page has no objects pointing to it.
1074                // We remark the page as orphaned to clear the tracedAfterOrphaned
1075                // flag and any object trace bits that were set during tracing.
1076                page->markOrphaned();
1077                prevNext = &entry->next;
1078                entry = entry->next;
1079                continue;
1080            }
1081
1082            // Page was not traced. Check if we should reuse the memory or just
1083            // free it. Large object memory is not reused, but freed, normal
1084            // blink heap pages are reused.
1085            // NOTE: We call the destructor before freeing or adding to the
1086            // free page pool.
1087            PageMemory* memory = page->storage();
1088            if (page->isLargeObject()) {
1089                page->~BaseHeapPage();
1090                delete memory;
1091            } else {
1092                page->~BaseHeapPage();
1093                // Clear out the page's memory before adding it to the free page
1094                // pool to ensure it is zero filled when being reused.
1095                clearMemory(memory);
1096                Heap::freePagePool()->addFreePage(index, memory);
1097            }
1098
1099            PoolEntry* deadEntry = entry;
1100            entry = entry->next;
1101            *prevNext = entry;
1102            delete deadEntry;
1103        }
1104    }
1105}
1106
1107NO_SANITIZE_ADDRESS
1108void OrphanedPagePool::clearMemory(PageMemory* memory)
1109{
1110#if defined(ADDRESS_SANITIZER)
1111    // Don't use memset when running with ASan since this needs to zap
1112    // poisoned memory as well and the NO_SANITIZE_ADDRESS annotation
1113    // only works for code in this method and not for calls to memset.
1114    Address base = memory->writableStart();
1115    for (Address current = base; current < base + blinkPagePayloadSize(); ++current)
1116        *current = 0;
1117#else
1118    memset(memory->writableStart(), 0, blinkPagePayloadSize());
1119#endif
1120}
1121
1122#if ENABLE(ASSERT)
1123bool OrphanedPagePool::contains(void* object)
1124{
1125    for (int index = 0; index < NumberOfHeaps; ++index) {
1126        for (PoolEntry* entry = m_pool[index]; entry; entry = entry->next) {
1127            BaseHeapPage* page = entry->data;
1128            if (page->contains(reinterpret_cast<Address>(object)))
1129                return true;
1130        }
1131    }
1132    return false;
1133}
1134#endif
1135
1136template<>
1137void ThreadHeap<FinalizedHeapObjectHeader>::addPageToHeap(const GCInfo* gcInfo)
1138{
1139    // When adding a page to the ThreadHeap using FinalizedHeapObjectHeaders the GCInfo on
1140    // the heap should be unused (ie. 0).
1141    allocatePage(0);
1142}
1143
1144template<>
1145void ThreadHeap<HeapObjectHeader>::addPageToHeap(const GCInfo* gcInfo)
1146{
1147    // When adding a page to the ThreadHeap using HeapObjectHeaders store the GCInfo on the heap
1148    // since it is the same for all objects
1149    ASSERT(gcInfo);
1150    allocatePage(gcInfo);
1151}
1152
1153template <typename Header>
1154void ThreadHeap<Header>::removePageFromHeap(HeapPage<Header>* page)
1155{
1156    MutexLocker locker(m_threadState->sweepMutex());
1157    flushHeapContainsCache();
1158    if (page->terminating()) {
1159        // The thread is shutting down so this page is being removed as part
1160        // of a thread local GC. In that case the page could be accessed in the
1161        // next global GC either due to a dead object being traced via a
1162        // conservative pointer or due to a programming error where an object
1163        // in another thread heap keeps a dangling pointer to this object.
1164        // To guard against this we put the page in the orphanedPagePool to
1165        // ensure it is still reachable. After the next global GC it can be
1166        // decommitted and moved to the page pool assuming no rogue/dangling
1167        // pointers refer to it.
1168        Heap::orphanedPagePool()->addOrphanedPage(m_index, page);
1169    } else {
1170        PageMemory* memory = page->storage();
1171        page->~HeapPage<Header>();
1172        Heap::freePagePool()->addFreePage(m_index, memory);
1173    }
1174}
1175
1176template<typename Header>
1177void ThreadHeap<Header>::allocatePage(const GCInfo* gcInfo)
1178{
1179    Heap::flushHeapDoesNotContainCache();
1180    PageMemory* pageMemory = Heap::freePagePool()->takeFreePage(m_index);
1181    // We continue allocating page memory until we succeed in getting one.
1182    // Since the FreePagePool is global other threads could use all the
1183    // newly allocated page memory before this thread calls takeFreePage.
1184    while (!pageMemory) {
1185        // Allocate a memory region for blinkPagesPerRegion pages that
1186        // will each have the following layout.
1187        //
1188        //    [ guard os page | ... payload ... | guard os page ]
1189        //    ^---{ aligned to blink page size }
1190        PageMemoryRegion* region = PageMemoryRegion::allocate(blinkPageSize * blinkPagesPerRegion, blinkPagesPerRegion);
1191        // Setup the PageMemory object for each of the pages in the
1192        // region.
1193        size_t offset = 0;
1194        for (size_t i = 0; i < blinkPagesPerRegion; i++) {
1195            Heap::freePagePool()->addFreePage(m_index, PageMemory::setupPageMemoryInRegion(region, offset, blinkPagePayloadSize()));
1196            offset += blinkPageSize;
1197        }
1198        pageMemory = Heap::freePagePool()->takeFreePage(m_index);
1199    }
1200    HeapPage<Header>* page = new (pageMemory->writableStart()) HeapPage<Header>(pageMemory, this, gcInfo);
1201    // Use a separate list for pages allocated during sweeping to make
1202    // sure that we do not accidentally sweep objects that have been
1203    // allocated during sweeping.
1204    if (m_threadState->isSweepInProgress()) {
1205        if (!m_lastPageAllocatedDuringSweeping)
1206            m_lastPageAllocatedDuringSweeping = page;
1207        page->link(&m_firstPageAllocatedDuringSweeping);
1208    } else {
1209        page->link(&m_firstPage);
1210    }
1211    ++m_numberOfNormalPages;
1212    addToFreeList(page->payload(), HeapPage<Header>::payloadSize());
1213}
1214
1215#if ENABLE(ASSERT)
1216template<typename Header>
1217bool ThreadHeap<Header>::pagesToBeSweptContains(Address address)
1218{
1219    for (HeapPage<Header>* page = m_firstPage; page; page = page->next()) {
1220        if (page->contains(address))
1221            return true;
1222    }
1223    return false;
1224}
1225
1226template<typename Header>
1227bool ThreadHeap<Header>::pagesAllocatedDuringSweepingContains(Address address)
1228{
1229    for (HeapPage<Header>* page = m_firstPageAllocatedDuringSweeping; page; page = page->next()) {
1230        if (page->contains(address))
1231            return true;
1232    }
1233    return false;
1234}
1235
1236template<typename Header>
1237void ThreadHeap<Header>::getScannedStats(HeapStats& scannedStats)
1238{
1239    ASSERT(!m_firstPageAllocatedDuringSweeping);
1240    for (HeapPage<Header>* page = m_firstPage; page; page = page->next())
1241        page->getStats(scannedStats);
1242    for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current; current = current->next())
1243        current->getStats(scannedStats);
1244}
1245#endif
1246
1247template<typename Header>
1248void ThreadHeap<Header>::sweepNormalPages(HeapStats* stats)
1249{
1250    TRACE_EVENT0("blink_gc", "ThreadHeap::sweepNormalPages");
1251    HeapPage<Header>* page = m_firstPage;
1252    HeapPage<Header>** previousNext = &m_firstPage;
1253    HeapPage<Header>* previous = 0;
1254    while (page) {
1255        page->resetPromptlyFreedSize();
1256        if (page->isEmpty()) {
1257            HeapPage<Header>* unused = page;
1258            if (unused == m_mergePoint)
1259                m_mergePoint = previous;
1260            page = page->next();
1261            HeapPage<Header>::unlink(this, unused, previousNext);
1262            --m_numberOfNormalPages;
1263        } else {
1264            page->sweep(stats, this);
1265            previousNext = &page->m_next;
1266            previous = page;
1267            page = page->next();
1268        }
1269    }
1270}
1271
1272template<typename Header>
1273void ThreadHeap<Header>::sweepLargePages(HeapStats* stats)
1274{
1275    TRACE_EVENT0("blink_gc", "ThreadHeap::sweepLargePages");
1276    LargeHeapObject<Header>** previousNext = &m_firstLargeHeapObject;
1277    for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current;) {
1278        if (current->isMarked()) {
1279            stats->increaseAllocatedSpace(current->size());
1280            stats->increaseObjectSpace(current->payloadSize());
1281            current->unmark();
1282            previousNext = &current->m_next;
1283            current = current->next();
1284        } else {
1285            LargeHeapObject<Header>* next = current->next();
1286            freeLargeObject(current, previousNext);
1287            current = next;
1288        }
1289    }
1290}
1291
1292
1293// STRICT_ASAN_FINALIZATION_CHECKING turns on poisoning of all objects during
1294// sweeping to catch cases where dead objects touch each other. This is not
1295// turned on by default because it also triggers for cases that are safe.
1296// Examples of such safe cases are context life cycle observers and timers
1297// embedded in garbage collected objects.
1298#define STRICT_ASAN_FINALIZATION_CHECKING 0
1299
1300template<typename Header>
1301void ThreadHeap<Header>::sweep(HeapStats* stats)
1302{
1303    ASSERT(isConsistentForSweeping());
1304#if defined(ADDRESS_SANITIZER) && STRICT_ASAN_FINALIZATION_CHECKING
1305    // When using ASan do a pre-sweep where all unmarked objects are
1306    // poisoned before calling their finalizer methods. This can catch
1307    // the case where the finalizer of an object tries to modify
1308    // another object as part of finalization.
1309    for (HeapPage<Header>* page = m_firstPage; page; page = page->next())
1310        page->poisonUnmarkedObjects();
1311#endif
1312    sweepNormalPages(stats);
1313    sweepLargePages(stats);
1314}
1315
1316template<typename Header>
1317void ThreadHeap<Header>::postSweepProcessing()
1318{
1319    // If pages have been allocated during sweeping, link them into
1320    // the list of pages.
1321    if (m_firstPageAllocatedDuringSweeping) {
1322        m_lastPageAllocatedDuringSweeping->m_next = m_firstPage;
1323        m_firstPage = m_firstPageAllocatedDuringSweeping;
1324        m_lastPageAllocatedDuringSweeping = 0;
1325        m_firstPageAllocatedDuringSweeping = 0;
1326    }
1327}
1328
1329#if ENABLE(ASSERT)
1330template<typename Header>
1331bool ThreadHeap<Header>::isConsistentForSweeping()
1332{
1333    // A thread heap is consistent for sweeping if none of the pages to
1334    // be swept contain a freelist block or the current allocation
1335    // point.
1336    for (size_t i = 0; i < blinkPageSizeLog2; i++) {
1337        for (FreeListEntry* freeListEntry = m_freeLists[i]; freeListEntry; freeListEntry = freeListEntry->next()) {
1338            if (pagesToBeSweptContains(freeListEntry->address())) {
1339                return false;
1340            }
1341            ASSERT(pagesAllocatedDuringSweepingContains(freeListEntry->address()));
1342        }
1343    }
1344    if (ownsNonEmptyAllocationArea()) {
1345        ASSERT(pagesToBeSweptContains(currentAllocationPoint())
1346            || pagesAllocatedDuringSweepingContains(currentAllocationPoint()));
1347        return !pagesToBeSweptContains(currentAllocationPoint());
1348    }
1349    return true;
1350}
1351#endif
1352
1353template<typename Header>
1354void ThreadHeap<Header>::makeConsistentForSweeping()
1355{
1356    if (ownsNonEmptyAllocationArea())
1357        addToFreeList(currentAllocationPoint(), remainingAllocationSize());
1358    setAllocationPoint(0, 0);
1359    clearFreeLists();
1360}
1361
1362template<typename Header>
1363void ThreadHeap<Header>::clearLiveAndMarkDead()
1364{
1365    ASSERT(isConsistentForSweeping());
1366    for (HeapPage<Header>* page = m_firstPage; page; page = page->next())
1367        page->clearLiveAndMarkDead();
1368    for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current; current = current->next()) {
1369        if (current->isMarked())
1370            current->unmark();
1371        else
1372            current->setDeadMark();
1373    }
1374}
1375
1376template<typename Header>
1377void ThreadHeap<Header>::clearFreeLists()
1378{
1379    m_promptlyFreedCount = 0;
1380    for (size_t i = 0; i < blinkPageSizeLog2; i++) {
1381        m_freeLists[i] = 0;
1382        m_lastFreeListEntries[i] = 0;
1383    }
1384}
1385
1386int BaseHeap::bucketIndexForSize(size_t size)
1387{
1388    ASSERT(size > 0);
1389    int index = -1;
1390    while (size) {
1391        size >>= 1;
1392        index++;
1393    }
1394    return index;
1395}
1396
1397template<typename Header>
1398HeapPage<Header>::HeapPage(PageMemory* storage, ThreadHeap<Header>* heap, const GCInfo* gcInfo)
1399    : BaseHeapPage(storage, gcInfo, heap->threadState())
1400    , m_next(0)
1401{
1402    COMPILE_ASSERT(!(sizeof(HeapPage<Header>) & allocationMask), page_header_incorrectly_aligned);
1403    m_objectStartBitMapComputed = false;
1404    ASSERT(isPageHeaderAddress(reinterpret_cast<Address>(this)));
1405    heap->stats().increaseAllocatedSpace(blinkPageSize);
1406}
1407
1408template<typename Header>
1409void HeapPage<Header>::link(HeapPage** prevNext)
1410{
1411    m_next = *prevNext;
1412    *prevNext = this;
1413}
1414
1415template<typename Header>
1416void HeapPage<Header>::unlink(ThreadHeap<Header>* heap, HeapPage* unused, HeapPage** prevNext)
1417{
1418    *prevNext = unused->m_next;
1419    heap->removePageFromHeap(unused);
1420}
1421
1422template<typename Header>
1423void HeapPage<Header>::getStats(HeapStats& stats)
1424{
1425    stats.increaseAllocatedSpace(blinkPageSize);
1426    Address headerAddress = payload();
1427    ASSERT(headerAddress != end());
1428    do {
1429        Header* header = reinterpret_cast<Header*>(headerAddress);
1430        if (!header->isFree())
1431            stats.increaseObjectSpace(header->payloadSize());
1432        ASSERT(header->size() < blinkPagePayloadSize());
1433        headerAddress += header->size();
1434        ASSERT(headerAddress <= end());
1435    } while (headerAddress < end());
1436}
1437
1438template<typename Header>
1439bool HeapPage<Header>::isEmpty()
1440{
1441    BasicObjectHeader* header = reinterpret_cast<BasicObjectHeader*>(payload());
1442    return header->isFree() && (header->size() == payloadSize());
1443}
1444
1445template<typename Header>
1446void HeapPage<Header>::sweep(HeapStats* stats, ThreadHeap<Header>* heap)
1447{
1448    clearObjectStartBitMap();
1449    stats->increaseAllocatedSpace(blinkPageSize);
1450    Address startOfGap = payload();
1451    for (Address headerAddress = startOfGap; headerAddress < end(); ) {
1452        BasicObjectHeader* basicHeader = reinterpret_cast<BasicObjectHeader*>(headerAddress);
1453        ASSERT(basicHeader->size() > 0);
1454        ASSERT(basicHeader->size() < blinkPagePayloadSize());
1455
1456        if (basicHeader->isFree()) {
1457            size_t size = basicHeader->size();
1458#if !ENABLE(ASSERT) && !defined(LEAK_SANITIZER) && !defined(ADDRESS_SANITIZER)
1459            // Zero the memory in the free list header to maintain the
1460            // invariant that memory on the free list is zero filled.
1461            // The rest of the memory is already on the free list and is
1462            // therefore already zero filled.
1463            if (size < sizeof(FreeListEntry))
1464                memset(headerAddress, 0, size);
1465            else
1466                memset(headerAddress, 0, sizeof(FreeListEntry));
1467#endif
1468            headerAddress += size;
1469            continue;
1470        }
1471        // At this point we know this is a valid object of type Header
1472        Header* header = static_cast<Header*>(basicHeader);
1473
1474        if (!header->isMarked()) {
1475            // For ASan we unpoison the specific object when calling the finalizer and
1476            // poison it again when done to allow the object's own finalizer to operate
1477            // on the object, but not have other finalizers be allowed to access it.
1478            ASAN_UNPOISON_MEMORY_REGION(header->payload(), header->payloadSize());
1479            finalize(header);
1480            size_t size = header->size();
1481#if !ENABLE(ASSERT) && !defined(LEAK_SANITIZER) && !defined(ADDRESS_SANITIZER)
1482            // This memory will be added to the freelist. Maintain the invariant
1483            // that memory on the freelist is zero filled.
1484            memset(headerAddress, 0, size);
1485#endif
1486            ASAN_POISON_MEMORY_REGION(header->payload(), header->payloadSize());
1487            headerAddress += size;
1488            continue;
1489        }
1490
1491        if (startOfGap != headerAddress)
1492            heap->addToFreeList(startOfGap, headerAddress - startOfGap);
1493        header->unmark();
1494        headerAddress += header->size();
1495        stats->increaseObjectSpace(header->payloadSize());
1496        startOfGap = headerAddress;
1497    }
1498    if (startOfGap != end())
1499        heap->addToFreeList(startOfGap, end() - startOfGap);
1500}
1501
1502template<typename Header>
1503void HeapPage<Header>::clearLiveAndMarkDead()
1504{
1505    for (Address headerAddress = payload(); headerAddress < end();) {
1506        Header* header = reinterpret_cast<Header*>(headerAddress);
1507        ASSERT(header->size() < blinkPagePayloadSize());
1508        // Check if a free list entry first since we cannot call
1509        // isMarked on a free list entry.
1510        if (header->isFree()) {
1511            headerAddress += header->size();
1512            continue;
1513        }
1514        if (header->isMarked())
1515            header->unmark();
1516        else
1517            header->setDeadMark();
1518        headerAddress += header->size();
1519    }
1520}
1521
1522template<typename Header>
1523void HeapPage<Header>::populateObjectStartBitMap()
1524{
1525    memset(&m_objectStartBitMap, 0, objectStartBitMapSize);
1526    Address start = payload();
1527    for (Address headerAddress = start; headerAddress < end();) {
1528        Header* header = reinterpret_cast<Header*>(headerAddress);
1529        size_t objectOffset = headerAddress - start;
1530        ASSERT(!(objectOffset & allocationMask));
1531        size_t objectStartNumber = objectOffset / allocationGranularity;
1532        size_t mapIndex = objectStartNumber / 8;
1533        ASSERT(mapIndex < objectStartBitMapSize);
1534        m_objectStartBitMap[mapIndex] |= (1 << (objectStartNumber & 7));
1535        headerAddress += header->size();
1536        ASSERT(headerAddress <= end());
1537    }
1538    m_objectStartBitMapComputed = true;
1539}
1540
1541template<typename Header>
1542void HeapPage<Header>::clearObjectStartBitMap()
1543{
1544    m_objectStartBitMapComputed = false;
1545}
1546
1547static int numberOfLeadingZeroes(uint8_t byte)
1548{
1549    if (!byte)
1550        return 8;
1551    int result = 0;
1552    if (byte <= 0x0F) {
1553        result += 4;
1554        byte = byte << 4;
1555    }
1556    if (byte <= 0x3F) {
1557        result += 2;
1558        byte = byte << 2;
1559    }
1560    if (byte <= 0x7F)
1561        result++;
1562    return result;
1563}
1564
1565template<typename Header>
1566Header* HeapPage<Header>::findHeaderFromAddress(Address address)
1567{
1568    if (address < payload())
1569        return 0;
1570    if (!isObjectStartBitMapComputed())
1571        populateObjectStartBitMap();
1572    size_t objectOffset = address - payload();
1573    size_t objectStartNumber = objectOffset / allocationGranularity;
1574    size_t mapIndex = objectStartNumber / 8;
1575    ASSERT(mapIndex < objectStartBitMapSize);
1576    size_t bit = objectStartNumber & 7;
1577    uint8_t byte = m_objectStartBitMap[mapIndex] & ((1 << (bit + 1)) - 1);
1578    while (!byte) {
1579        ASSERT(mapIndex > 0);
1580        byte = m_objectStartBitMap[--mapIndex];
1581    }
1582    int leadingZeroes = numberOfLeadingZeroes(byte);
1583    objectStartNumber = (mapIndex * 8) + 7 - leadingZeroes;
1584    objectOffset = objectStartNumber * allocationGranularity;
1585    Address objectAddress = objectOffset + payload();
1586    Header* header = reinterpret_cast<Header*>(objectAddress);
1587    if (header->isFree())
1588        return 0;
1589    return header;
1590}
1591
1592template<typename Header>
1593void HeapPage<Header>::checkAndMarkPointer(Visitor* visitor, Address address)
1594{
1595    ASSERT(contains(address));
1596    Header* header = findHeaderFromAddress(address);
1597    if (!header || header->hasDeadMark())
1598        return;
1599
1600#if ENABLE(GC_PROFILE_MARKING)
1601    visitor->setHostInfo(&address, "stack");
1602#endif
1603    if (hasVTable(header) && !vTableInitialized(header->payload())) {
1604        visitor->markNoTracing(header);
1605        ASSERT(isUninitializedMemory(header->payload(), header->payloadSize()));
1606    } else {
1607        visitor->mark(header, traceCallback(header));
1608    }
1609}
1610
1611#if ENABLE(GC_PROFILE_MARKING)
1612template<typename Header>
1613const GCInfo* HeapPage<Header>::findGCInfo(Address address)
1614{
1615    if (address < payload())
1616        return 0;
1617
1618    if (gcInfo()) // for non FinalizedObjectHeader
1619        return gcInfo();
1620
1621    Header* header = findHeaderFromAddress(address);
1622    if (!header)
1623        return 0;
1624
1625    return header->gcInfo();
1626}
1627#endif
1628
1629#if ENABLE(GC_PROFILE_HEAP)
1630template<typename Header>
1631void HeapPage<Header>::snapshot(TracedValue* json, ThreadState::SnapshotInfo* info)
1632{
1633    Header* header = 0;
1634    for (Address addr = payload(); addr < end(); addr += header->size()) {
1635        header = reinterpret_cast<Header*>(addr);
1636        if (json)
1637            json->pushInteger(header->encodedSize());
1638        if (header->isFree()) {
1639            info->freeSize += header->size();
1640            continue;
1641        }
1642
1643        const GCInfo* gcinfo = header->gcInfo() ? header->gcInfo() : gcInfo();
1644        size_t tag = info->getClassTag(gcinfo);
1645        size_t age = header->age();
1646        if (json)
1647            json->pushInteger(tag);
1648        if (header->isMarked()) {
1649            info->liveCount[tag] += 1;
1650            info->liveSize[tag] += header->size();
1651            // Count objects that are live when promoted to the final generation.
1652            if (age == maxHeapObjectAge - 1)
1653                info->generations[tag][maxHeapObjectAge] += 1;
1654            header->incAge();
1655        } else {
1656            info->deadCount[tag] += 1;
1657            info->deadSize[tag] += header->size();
1658            // Count objects that are dead before the final generation.
1659            if (age < maxHeapObjectAge)
1660                info->generations[tag][age] += 1;
1661        }
1662    }
1663}
1664#endif
1665
1666#if defined(ADDRESS_SANITIZER)
1667template<typename Header>
1668void HeapPage<Header>::poisonUnmarkedObjects()
1669{
1670    for (Address headerAddress = payload(); headerAddress < end(); ) {
1671        Header* header = reinterpret_cast<Header*>(headerAddress);
1672        ASSERT(header->size() < blinkPagePayloadSize());
1673
1674        if (!header->isFree() && !header->isMarked())
1675            ASAN_POISON_MEMORY_REGION(header->payload(), header->payloadSize());
1676        headerAddress += header->size();
1677    }
1678}
1679#endif
1680
1681template<>
1682inline void HeapPage<FinalizedHeapObjectHeader>::finalize(FinalizedHeapObjectHeader* header)
1683{
1684    header->finalize();
1685}
1686
1687template<>
1688inline void HeapPage<HeapObjectHeader>::finalize(HeapObjectHeader* header)
1689{
1690    ASSERT(gcInfo());
1691    HeapObjectHeader::finalize(gcInfo(), header->payload(), header->payloadSize());
1692}
1693
1694template<>
1695inline TraceCallback HeapPage<HeapObjectHeader>::traceCallback(HeapObjectHeader* header)
1696{
1697    ASSERT(gcInfo());
1698    return gcInfo()->m_trace;
1699}
1700
1701template<>
1702inline TraceCallback HeapPage<FinalizedHeapObjectHeader>::traceCallback(FinalizedHeapObjectHeader* header)
1703{
1704    return header->traceCallback();
1705}
1706
1707template<>
1708inline bool HeapPage<HeapObjectHeader>::hasVTable(HeapObjectHeader* header)
1709{
1710    ASSERT(gcInfo());
1711    return gcInfo()->hasVTable();
1712}
1713
1714template<>
1715inline bool HeapPage<FinalizedHeapObjectHeader>::hasVTable(FinalizedHeapObjectHeader* header)
1716{
1717    return header->hasVTable();
1718}
1719
1720template<typename Header>
1721void LargeHeapObject<Header>::getStats(HeapStats& stats)
1722{
1723    stats.increaseAllocatedSpace(size());
1724    stats.increaseObjectSpace(payloadSize());
1725}
1726
1727#if ENABLE(GC_PROFILE_HEAP)
1728template<typename Header>
1729void LargeHeapObject<Header>::snapshot(TracedValue* json, ThreadState::SnapshotInfo* info)
1730{
1731    Header* header = heapObjectHeader();
1732    size_t tag = info->getClassTag(header->gcInfo());
1733    size_t age = header->age();
1734    if (isMarked()) {
1735        info->liveCount[tag] += 1;
1736        info->liveSize[tag] += header->size();
1737        // Count objects that are live when promoted to the final generation.
1738        if (age == maxHeapObjectAge - 1)
1739            info->generations[tag][maxHeapObjectAge] += 1;
1740        header->incAge();
1741    } else {
1742        info->deadCount[tag] += 1;
1743        info->deadSize[tag] += header->size();
1744        // Count objects that are dead before the final generation.
1745        if (age < maxHeapObjectAge)
1746            info->generations[tag][age] += 1;
1747    }
1748
1749    if (json) {
1750        json->setInteger("class", tag);
1751        json->setInteger("size", header->size());
1752        json->setInteger("isMarked", isMarked());
1753    }
1754}
1755#endif
1756
1757template<typename Entry>
1758void HeapExtentCache<Entry>::flush()
1759{
1760    if (m_hasEntries) {
1761        for (int i = 0; i < numberOfEntries; i++)
1762            m_entries[i] = Entry();
1763        m_hasEntries = false;
1764    }
1765}
1766
1767template<typename Entry>
1768size_t HeapExtentCache<Entry>::hash(Address address)
1769{
1770    size_t value = (reinterpret_cast<size_t>(address) >> blinkPageSizeLog2);
1771    value ^= value >> numberOfEntriesLog2;
1772    value ^= value >> (numberOfEntriesLog2 * 2);
1773    value &= numberOfEntries - 1;
1774    return value & ~1; // Returns only even number.
1775}
1776
1777template<typename Entry>
1778typename Entry::LookupResult HeapExtentCache<Entry>::lookup(Address address)
1779{
1780    size_t index = hash(address);
1781    ASSERT(!(index & 1));
1782    Address cachePage = roundToBlinkPageStart(address);
1783    if (m_entries[index].address() == cachePage)
1784        return m_entries[index].result();
1785    if (m_entries[index + 1].address() == cachePage)
1786        return m_entries[index + 1].result();
1787    return 0;
1788}
1789
1790template<typename Entry>
1791void HeapExtentCache<Entry>::addEntry(Address address, typename Entry::LookupResult entry)
1792{
1793    m_hasEntries = true;
1794    size_t index = hash(address);
1795    ASSERT(!(index & 1));
1796    Address cachePage = roundToBlinkPageStart(address);
1797    m_entries[index + 1] = m_entries[index];
1798    m_entries[index] = Entry(cachePage, entry);
1799}
1800
1801// These should not be needed, but it seems impossible to persuade clang to
1802// instantiate the template functions and export them from a shared library, so
1803// we add these in the non-templated subclass, which does not have that issue.
1804void HeapContainsCache::addEntry(Address address, BaseHeapPage* page)
1805{
1806    HeapExtentCache<PositiveEntry>::addEntry(address, page);
1807}
1808
1809BaseHeapPage* HeapContainsCache::lookup(Address address)
1810{
1811    return HeapExtentCache<PositiveEntry>::lookup(address);
1812}
1813
1814void Heap::flushHeapDoesNotContainCache()
1815{
1816    s_heapDoesNotContainCache->flush();
1817}
1818
1819// The marking mutex is used to ensure sequential access to data
1820// structures during marking. The marking mutex needs to be acquired
1821// during marking when elements are taken from the global marking
1822// stack or when elements are added to the global ephemeron,
1823// post-marking, and weak processing stacks. In debug mode the mutex
1824// also needs to be acquired when asserts use the heap contains
1825// caches.
1826static Mutex& markingMutex()
1827{
1828    AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
1829    return mutex;
1830}
1831
1832static ThreadCondition& markingCondition()
1833{
1834    AtomicallyInitializedStatic(ThreadCondition&, condition = *new ThreadCondition);
1835    return condition;
1836}
1837
1838static void markNoTracingCallback(Visitor* visitor, void* object)
1839{
1840    visitor->markNoTracing(object);
1841}
1842
1843class MarkingVisitor : public Visitor {
1844public:
1845#if ENABLE(GC_PROFILE_MARKING)
1846    typedef HashSet<uintptr_t> LiveObjectSet;
1847    typedef HashMap<String, LiveObjectSet> LiveObjectMap;
1848    typedef HashMap<uintptr_t, std::pair<uintptr_t, String> > ObjectGraph;
1849#endif
1850
1851    MarkingVisitor(CallbackStack* markingStack) : m_markingStack(markingStack)
1852    {
1853    }
1854
1855    inline void visitHeader(HeapObjectHeader* header, const void* objectPointer, TraceCallback callback)
1856    {
1857        ASSERT(header);
1858#if ENABLE(ASSERT)
1859        {
1860            // Check that we are not marking objects that are outside
1861            // the heap by calling Heap::contains. However we cannot
1862            // call Heap::contains when outside a GC and we call mark
1863            // when doing weakness for ephemerons. Hence we only check
1864            // when called within.
1865            MutexLocker locker(markingMutex());
1866            ASSERT(!ThreadState::isAnyThreadInGC() || Heap::containedInHeapOrOrphanedPage(header));
1867        }
1868#endif
1869        ASSERT(objectPointer);
1870        if (header->isMarked())
1871            return;
1872        header->mark();
1873#if ENABLE(GC_PROFILE_MARKING)
1874        MutexLocker locker(objectGraphMutex());
1875        String className(classOf(objectPointer));
1876        {
1877            LiveObjectMap::AddResult result = currentlyLive().add(className, LiveObjectSet());
1878            result.storedValue->value.add(reinterpret_cast<uintptr_t>(objectPointer));
1879        }
1880        ObjectGraph::AddResult result = objectGraph().add(reinterpret_cast<uintptr_t>(objectPointer), std::make_pair(reinterpret_cast<uintptr_t>(m_hostObject), m_hostName));
1881        ASSERT(result.isNewEntry);
1882        // fprintf(stderr, "%s[%p] -> %s[%p]\n", m_hostName.ascii().data(), m_hostObject, className.ascii().data(), objectPointer);
1883#endif
1884        if (callback)
1885            Heap::pushTraceCallback(m_markingStack, const_cast<void*>(objectPointer), callback);
1886    }
1887
1888    virtual void mark(HeapObjectHeader* header, TraceCallback callback) OVERRIDE
1889    {
1890        // We need both the HeapObjectHeader and FinalizedHeapObjectHeader
1891        // version to correctly find the payload.
1892        visitHeader(header, header->payload(), callback);
1893    }
1894
1895    virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) OVERRIDE
1896    {
1897        // We need both the HeapObjectHeader and FinalizedHeapObjectHeader
1898        // version to correctly find the payload.
1899        visitHeader(header, header->payload(), callback);
1900    }
1901
1902    virtual void mark(const void* objectPointer, TraceCallback callback) OVERRIDE
1903    {
1904        if (!objectPointer)
1905            return;
1906        FinalizedHeapObjectHeader* header = FinalizedHeapObjectHeader::fromPayload(objectPointer);
1907        visitHeader(header, header->payload(), callback);
1908    }
1909
1910    virtual void registerDelayedMarkNoTracing(const void* object) OVERRIDE
1911    {
1912        Heap::pushPostMarkingCallback(const_cast<void*>(object), markNoTracingCallback);
1913    }
1914
1915    virtual void registerWeakMembers(const void* closure, const void* containingObject, WeakPointerCallback callback) OVERRIDE
1916    {
1917        Heap::pushWeakObjectPointerCallback(const_cast<void*>(closure), const_cast<void*>(containingObject), callback);
1918    }
1919
1920    virtual void registerWeakTable(const void* closure, EphemeronCallback iterationCallback, EphemeronCallback iterationDoneCallback)
1921    {
1922        Heap::registerWeakTable(const_cast<void*>(closure), iterationCallback, iterationDoneCallback);
1923    }
1924
1925#if ENABLE(ASSERT)
1926    virtual bool weakTableRegistered(const void* closure)
1927    {
1928        return Heap::weakTableRegistered(closure);
1929    }
1930#endif
1931
1932    virtual bool isMarked(const void* objectPointer) OVERRIDE
1933    {
1934        return FinalizedHeapObjectHeader::fromPayload(objectPointer)->isMarked();
1935    }
1936
1937    // This macro defines the necessary visitor methods for typed heaps
1938#define DEFINE_VISITOR_METHODS(Type)                                              \
1939    virtual void mark(const Type* objectPointer, TraceCallback callback) OVERRIDE \
1940    {                                                                             \
1941        if (!objectPointer)                                                       \
1942            return;                                                               \
1943        HeapObjectHeader* header =                                                \
1944            HeapObjectHeader::fromPayload(objectPointer);                         \
1945        visitHeader(header, header->payload(), callback);                         \
1946    }                                                                             \
1947    virtual bool isMarked(const Type* objectPointer) OVERRIDE                     \
1948    {                                                                             \
1949        return HeapObjectHeader::fromPayload(objectPointer)->isMarked();          \
1950    }
1951
1952    FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)
1953#undef DEFINE_VISITOR_METHODS
1954
1955#if ENABLE(GC_PROFILE_MARKING)
1956    void reportStats()
1957    {
1958        fprintf(stderr, "\n---------- AFTER MARKING -------------------\n");
1959        for (LiveObjectMap::iterator it = currentlyLive().begin(), end = currentlyLive().end(); it != end; ++it) {
1960            fprintf(stderr, "%s %u", it->key.ascii().data(), it->value.size());
1961
1962            if (it->key == "blink::Document")
1963                reportStillAlive(it->value, previouslyLive().get(it->key));
1964
1965            fprintf(stderr, "\n");
1966        }
1967
1968        previouslyLive().swap(currentlyLive());
1969        currentlyLive().clear();
1970
1971        for (HashSet<uintptr_t>::iterator it = objectsToFindPath().begin(), end = objectsToFindPath().end(); it != end; ++it) {
1972            dumpPathToObjectFromObjectGraph(objectGraph(), *it);
1973        }
1974    }
1975
1976    static void reportStillAlive(LiveObjectSet current, LiveObjectSet previous)
1977    {
1978        int count = 0;
1979
1980        fprintf(stderr, " [previously %u]", previous.size());
1981        for (LiveObjectSet::iterator it = current.begin(), end = current.end(); it != end; ++it) {
1982            if (previous.find(*it) == previous.end())
1983                continue;
1984            count++;
1985        }
1986
1987        if (!count)
1988            return;
1989
1990        fprintf(stderr, " {survived 2GCs %d: ", count);
1991        for (LiveObjectSet::iterator it = current.begin(), end = current.end(); it != end; ++it) {
1992            if (previous.find(*it) == previous.end())
1993                continue;
1994            fprintf(stderr, "%ld", *it);
1995            if (--count)
1996                fprintf(stderr, ", ");
1997        }
1998        ASSERT(!count);
1999        fprintf(stderr, "}");
2000    }
2001
2002    static void dumpPathToObjectFromObjectGraph(const ObjectGraph& graph, uintptr_t target)
2003    {
2004        ObjectGraph::const_iterator it = graph.find(target);
2005        if (it == graph.end())
2006            return;
2007        fprintf(stderr, "Path to %lx of %s\n", target, classOf(reinterpret_cast<const void*>(target)).ascii().data());
2008        while (it != graph.end()) {
2009            fprintf(stderr, "<- %lx of %s\n", it->value.first, it->value.second.utf8().data());
2010            it = graph.find(it->value.first);
2011        }
2012        fprintf(stderr, "\n");
2013    }
2014
2015    static void dumpPathToObjectOnNextGC(void* p)
2016    {
2017        objectsToFindPath().add(reinterpret_cast<uintptr_t>(p));
2018    }
2019
2020    static Mutex& objectGraphMutex()
2021    {
2022        AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
2023        return mutex;
2024    }
2025
2026    static LiveObjectMap& previouslyLive()
2027    {
2028        DEFINE_STATIC_LOCAL(LiveObjectMap, map, ());
2029        return map;
2030    }
2031
2032    static LiveObjectMap& currentlyLive()
2033    {
2034        DEFINE_STATIC_LOCAL(LiveObjectMap, map, ());
2035        return map;
2036    }
2037
2038    static ObjectGraph& objectGraph()
2039    {
2040        DEFINE_STATIC_LOCAL(ObjectGraph, graph, ());
2041        return graph;
2042    }
2043
2044    static HashSet<uintptr_t>& objectsToFindPath()
2045    {
2046        DEFINE_STATIC_LOCAL(HashSet<uintptr_t>, set, ());
2047        return set;
2048    }
2049#endif
2050
2051protected:
2052    virtual void registerWeakCell(void** cell, WeakPointerCallback callback) OVERRIDE
2053    {
2054        Heap::pushWeakCellPointerCallback(cell, callback);
2055    }
2056
2057private:
2058    CallbackStack* m_markingStack;
2059};
2060
2061void Heap::init()
2062{
2063    ThreadState::init();
2064    s_markingStack = new CallbackStack();
2065    s_postMarkingCallbackStack = new CallbackStack();
2066    s_weakCallbackStack = new CallbackStack();
2067    s_ephemeronStack = new CallbackStack();
2068    s_heapDoesNotContainCache = new HeapDoesNotContainCache();
2069    s_markingVisitor = new MarkingVisitor(s_markingStack);
2070    s_freePagePool = new FreePagePool();
2071    s_orphanedPagePool = new OrphanedPagePool();
2072    s_markingThreads = new Vector<OwnPtr<blink::WebThread> >();
2073    if (blink::Platform::current()) {
2074        // FIXME: We should let the amount of threads scale with the
2075        // amount of processors in the system instead of hardcoding
2076        // it.
2077        for (int i = 0; i < numberOfMarkingThreads; i++)
2078            s_markingThreads->append(adoptPtr(blink::Platform::current()->createThread("Blink Heap Marker Thread")));
2079    }
2080}
2081
2082void Heap::shutdown()
2083{
2084    s_shutdownCalled = true;
2085    ThreadState::shutdownHeapIfNecessary();
2086}
2087
2088void Heap::doShutdown()
2089{
2090    // We don't want to call doShutdown() twice.
2091    if (!s_markingVisitor)
2092        return;
2093
2094    ASSERT(!ThreadState::isAnyThreadInGC());
2095    ASSERT(!ThreadState::attachedThreads().size());
2096    delete s_markingThreads;
2097    s_markingThreads = 0;
2098    delete s_markingVisitor;
2099    s_markingVisitor = 0;
2100    delete s_heapDoesNotContainCache;
2101    s_heapDoesNotContainCache = 0;
2102    delete s_freePagePool;
2103    s_freePagePool = 0;
2104    delete s_orphanedPagePool;
2105    s_orphanedPagePool = 0;
2106    delete s_weakCallbackStack;
2107    s_weakCallbackStack = 0;
2108    delete s_postMarkingCallbackStack;
2109    s_postMarkingCallbackStack = 0;
2110    delete s_markingStack;
2111    s_markingStack = 0;
2112    delete s_ephemeronStack;
2113    s_ephemeronStack = 0;
2114    ThreadState::shutdown();
2115}
2116
2117BaseHeapPage* Heap::contains(Address address)
2118{
2119    ASSERT(ThreadState::isAnyThreadInGC());
2120    ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads();
2121    for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it) {
2122        BaseHeapPage* page = (*it)->contains(address);
2123        if (page)
2124            return page;
2125    }
2126    return 0;
2127}
2128
2129#if ENABLE(ASSERT)
2130bool Heap::containedInHeapOrOrphanedPage(void* object)
2131{
2132    return contains(object) || orphanedPagePool()->contains(object);
2133}
2134#endif
2135
2136Address Heap::checkAndMarkPointer(Visitor* visitor, Address address)
2137{
2138    ASSERT(ThreadState::isAnyThreadInGC());
2139
2140#if !ENABLE(ASSERT)
2141    if (s_heapDoesNotContainCache->lookup(address))
2142        return 0;
2143#endif
2144
2145    ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads();
2146    for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it) {
2147        if ((*it)->checkAndMarkPointer(visitor, address)) {
2148            // Pointer was in a page of that thread. If it actually pointed
2149            // into an object then that object was found and marked.
2150            ASSERT(!s_heapDoesNotContainCache->lookup(address));
2151            s_lastGCWasConservative = true;
2152            return address;
2153        }
2154    }
2155
2156#if !ENABLE(ASSERT)
2157    s_heapDoesNotContainCache->addEntry(address, true);
2158#else
2159    if (!s_heapDoesNotContainCache->lookup(address))
2160        s_heapDoesNotContainCache->addEntry(address, true);
2161#endif
2162    return 0;
2163}
2164
2165#if ENABLE(GC_PROFILE_MARKING)
2166const GCInfo* Heap::findGCInfo(Address address)
2167{
2168    return ThreadState::findGCInfoFromAllThreads(address);
2169}
2170#endif
2171
2172#if ENABLE(GC_PROFILE_MARKING)
2173void Heap::dumpPathToObjectOnNextGC(void* p)
2174{
2175    static_cast<MarkingVisitor*>(s_markingVisitor)->dumpPathToObjectOnNextGC(p);
2176}
2177
2178String Heap::createBacktraceString()
2179{
2180    int framesToShow = 3;
2181    int stackFrameSize = 16;
2182    ASSERT(stackFrameSize >= framesToShow);
2183    typedef void* FramePointer;
2184    FramePointer* stackFrame = static_cast<FramePointer*>(alloca(sizeof(FramePointer) * stackFrameSize));
2185    WTFGetBacktrace(stackFrame, &stackFrameSize);
2186
2187    StringBuilder builder;
2188    builder.append("Persistent");
2189    bool didAppendFirstName = false;
2190    // Skip frames before/including "blink::Persistent".
2191    bool didSeePersistent = false;
2192    for (int i = 0; i < stackFrameSize && framesToShow > 0; ++i) {
2193        FrameToNameScope frameToName(stackFrame[i]);
2194        if (!frameToName.nullableName())
2195            continue;
2196        if (strstr(frameToName.nullableName(), "blink::Persistent")) {
2197            didSeePersistent = true;
2198            continue;
2199        }
2200        if (!didSeePersistent)
2201            continue;
2202        if (!didAppendFirstName) {
2203            didAppendFirstName = true;
2204            builder.append(" ... Backtrace:");
2205        }
2206        builder.append("\n\t");
2207        builder.append(frameToName.nullableName());
2208        --framesToShow;
2209    }
2210    return builder.toString().replace("blink::", "");
2211}
2212#endif
2213
2214void Heap::pushTraceCallback(CallbackStack* stack, void* object, TraceCallback callback)
2215{
2216#if ENABLE(ASSERT)
2217    {
2218        MutexLocker locker(markingMutex());
2219        ASSERT(Heap::containedInHeapOrOrphanedPage(object));
2220    }
2221#endif
2222    CallbackStack::Item* slot = stack->allocateEntry();
2223    *slot = CallbackStack::Item(object, callback);
2224}
2225
2226template<CallbackInvocationMode Mode>
2227bool Heap::popAndInvokeTraceCallback(CallbackStack* stack, Visitor* visitor)
2228{
2229    CallbackStack::Item* item = stack->pop();
2230    if (!item)
2231        return false;
2232    // If the object being traced is located on a page which is dead don't
2233    // trace it. This can happen when a conservative GC kept a dead object
2234    // alive which pointed to a (now gone) object on the cleaned up page.
2235    // Also, if doing a thread local GC, don't trace objects that are located
2236    // on other thread's heaps, ie, pages where the terminating flag is not set.
2237    BaseHeapPage* heapPage = pageHeaderFromObject(item->object());
2238    if (Mode == GlobalMarking && heapPage->orphaned()) {
2239        // When doing a global GC we should only get a trace callback to an orphaned
2240        // page if the GC is conservative. If it is not conservative there is
2241        // a bug in the code where we have a dangling pointer to a page
2242        // on the dead thread.
2243        RELEASE_ASSERT(Heap::lastGCWasConservative());
2244        heapPage->setTracedAfterOrphaned();
2245        return true;
2246    }
2247    if (Mode == ThreadLocalMarking && (heapPage->orphaned() || !heapPage->terminating()))
2248        return true;
2249
2250#if ENABLE(GC_PROFILE_MARKING)
2251    visitor->setHostInfo(item->object(), classOf(item->object()));
2252#endif
2253    item->call(visitor);
2254    return true;
2255}
2256
2257void Heap::pushPostMarkingCallback(void* object, TraceCallback callback)
2258{
2259    MutexLocker locker(markingMutex());
2260    ASSERT(!Heap::orphanedPagePool()->contains(object));
2261    CallbackStack::Item* slot = s_postMarkingCallbackStack->allocateEntry();
2262    *slot = CallbackStack::Item(object, callback);
2263}
2264
2265bool Heap::popAndInvokePostMarkingCallback(Visitor* visitor)
2266{
2267    if (CallbackStack::Item* item = s_postMarkingCallbackStack->pop()) {
2268        item->call(visitor);
2269        return true;
2270    }
2271    return false;
2272}
2273
2274void Heap::pushWeakCellPointerCallback(void** cell, WeakPointerCallback callback)
2275{
2276    MutexLocker locker(markingMutex());
2277    ASSERT(!Heap::orphanedPagePool()->contains(cell));
2278    CallbackStack::Item* slot = s_weakCallbackStack->allocateEntry();
2279    *slot = CallbackStack::Item(cell, callback);
2280}
2281
2282void Heap::pushWeakObjectPointerCallback(void* closure, void* object, WeakPointerCallback callback)
2283{
2284    MutexLocker locker(markingMutex());
2285    ASSERT(Heap::contains(object));
2286    BaseHeapPage* heapPageForObject = pageHeaderFromObject(object);
2287    ASSERT(!heapPageForObject->orphaned());
2288    ASSERT(Heap::contains(object) == heapPageForObject);
2289    ThreadState* state = heapPageForObject->threadState();
2290    state->pushWeakObjectPointerCallback(closure, callback);
2291}
2292
2293bool Heap::popAndInvokeWeakPointerCallback(Visitor* visitor)
2294{
2295    // For weak processing we should never reach orphaned pages since orphaned
2296    // pages are not traced and thus objects on those pages are never be
2297    // registered as objects on orphaned pages. We cannot assert this here since
2298    // we might have an off-heap collection. We assert it in
2299    // Heap::pushWeakObjectPointerCallback.
2300    if (CallbackStack::Item* item = s_weakCallbackStack->pop()) {
2301        item->call(visitor);
2302        return true;
2303    }
2304    return false;
2305}
2306
2307void Heap::registerWeakTable(void* table, EphemeronCallback iterationCallback, EphemeronCallback iterationDoneCallback)
2308{
2309    {
2310        MutexLocker locker(markingMutex());
2311        // Check that the ephemeron table being pushed onto the stack is not on an
2312        // orphaned page.
2313        ASSERT(!Heap::orphanedPagePool()->contains(table));
2314        CallbackStack::Item* slot = s_ephemeronStack->allocateEntry();
2315        *slot = CallbackStack::Item(table, iterationCallback);
2316    }
2317
2318    // Register a post-marking callback to tell the tables that
2319    // ephemeron iteration is complete.
2320    pushPostMarkingCallback(table, iterationDoneCallback);
2321}
2322
2323#if ENABLE(ASSERT)
2324bool Heap::weakTableRegistered(const void* table)
2325{
2326    MutexLocker locker(markingMutex());
2327    ASSERT(s_ephemeronStack);
2328    return s_ephemeronStack->hasCallbackForObject(table);
2329}
2330#endif
2331
2332void Heap::prepareForGC()
2333{
2334    ASSERT(ThreadState::isAnyThreadInGC());
2335    ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads();
2336    for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it)
2337        (*it)->prepareForGC();
2338}
2339
2340void Heap::collectGarbage(ThreadState::StackState stackState, ThreadState::CauseOfGC cause)
2341{
2342    ThreadState* state = ThreadState::current();
2343    state->clearGCRequested();
2344
2345    GCScope gcScope(stackState);
2346    // Check if we successfully parked the other threads. If not we bail out of the GC.
2347    if (!gcScope.allThreadsParked()) {
2348        ThreadState::current()->setGCRequested();
2349        return;
2350    }
2351
2352    if (state->isMainThread())
2353        ScriptForbiddenScope::enter();
2354
2355    s_lastGCWasConservative = false;
2356
2357    TRACE_EVENT2("blink_gc", "Heap::collectGarbage",
2358        "precise", stackState == ThreadState::NoHeapPointersOnStack,
2359        "forced", cause == ThreadState::ForcedGC);
2360    TRACE_EVENT_SCOPED_SAMPLING_STATE("blink_gc", "BlinkGC");
2361    double timeStamp = WTF::currentTimeMS();
2362#if ENABLE(GC_PROFILE_MARKING)
2363    static_cast<MarkingVisitor*>(s_markingVisitor)->objectGraph().clear();
2364#endif
2365
2366    // Disallow allocation during garbage collection (but not
2367    // during the finalization that happens when the gcScope is
2368    // torn down).
2369    NoAllocationScope<AnyThread> noAllocationScope;
2370
2371    prepareForGC();
2372
2373    // 1. trace persistent roots.
2374    ThreadState::visitPersistentRoots(s_markingVisitor);
2375
2376    // 2. trace objects reachable from the persistent roots including ephemerons.
2377    processMarkingStackInParallel();
2378
2379    // 3. trace objects reachable from the stack. We do this independent of the
2380    // given stackState since other threads might have a different stack state.
2381    ThreadState::visitStackRoots(s_markingVisitor);
2382
2383    // 4. trace objects reachable from the stack "roots" including ephemerons.
2384    // Only do the processing if we found a pointer to an object on one of the
2385    // thread stacks.
2386    if (lastGCWasConservative())
2387        processMarkingStackInParallel();
2388
2389    postMarkingProcessing();
2390    globalWeakProcessing();
2391
2392    // After a global marking we know that any orphaned page that was not reached
2393    // cannot be reached in a subsequent GC. This is due to a thread either having
2394    // swept its heap or having done a "poor mans sweep" in prepareForGC which marks
2395    // objects that are dead, but not swept in the previous GC as dead. In this GC's
2396    // marking we check that any object marked as dead is not traced. E.g. via a
2397    // conservatively found pointer or a programming error with an object containing
2398    // a dangling pointer.
2399    orphanedPagePool()->decommitOrphanedPages();
2400
2401#if ENABLE(GC_PROFILE_MARKING)
2402    static_cast<MarkingVisitor*>(s_markingVisitor)->reportStats();
2403#endif
2404
2405    if (blink::Platform::current()) {
2406        uint64_t objectSpaceSize;
2407        uint64_t allocatedSpaceSize;
2408        getHeapSpaceSize(&objectSpaceSize, &allocatedSpaceSize);
2409        blink::Platform::current()->histogramCustomCounts("BlinkGC.CollectGarbage", WTF::currentTimeMS() - timeStamp, 0, 10 * 1000, 50);
2410        blink::Platform::current()->histogramCustomCounts("BlinkGC.TotalObjectSpace", objectSpaceSize / 1024, 0, 4 * 1024 * 1024, 50);
2411        blink::Platform::current()->histogramCustomCounts("BlinkGC.TotalAllocatedSpace", allocatedSpaceSize / 1024, 0, 4 * 1024 * 1024, 50);
2412    }
2413
2414    if (state->isMainThread())
2415        ScriptForbiddenScope::exit();
2416}
2417
2418void Heap::collectGarbageForTerminatingThread(ThreadState* state)
2419{
2420    // We explicitly do not enter a safepoint while doing thread specific
2421    // garbage collection since we don't want to allow a global GC at the
2422    // same time as a thread local GC.
2423
2424    {
2425        NoAllocationScope<AnyThread> noAllocationScope;
2426
2427        state->enterGC();
2428        state->prepareForGC();
2429
2430        // 1. trace the thread local persistent roots. For thread local GCs we
2431        // don't trace the stack (ie. no conservative scanning) since this is
2432        // only called during thread shutdown where there should be no objects
2433        // on the stack.
2434        // We also assume that orphaned pages have no objects reachable from
2435        // persistent handles on other threads or CrossThreadPersistents. The
2436        // only cases where this could happen is if a subsequent conservative
2437        // global GC finds a "pointer" on the stack or due to a programming
2438        // error where an object has a dangling cross-thread pointer to an
2439        // object on this heap.
2440        state->visitPersistents(s_markingVisitor);
2441
2442        // 2. trace objects reachable from the thread's persistent roots
2443        // including ephemerons.
2444        processMarkingStack<ThreadLocalMarking>();
2445
2446        postMarkingProcessing();
2447        globalWeakProcessing();
2448
2449        state->leaveGC();
2450    }
2451    state->performPendingSweep();
2452}
2453
2454void Heap::processMarkingStackEntries(int* runningMarkingThreads)
2455{
2456    TRACE_EVENT0("blink_gc", "Heap::processMarkingStackEntries");
2457    CallbackStack stack;
2458    MarkingVisitor visitor(&stack);
2459    {
2460        MutexLocker locker(markingMutex());
2461        stack.takeBlockFrom(s_markingStack);
2462    }
2463    while (!stack.isEmpty()) {
2464        while (popAndInvokeTraceCallback<GlobalMarking>(&stack, &visitor)) { }
2465        {
2466            MutexLocker locker(markingMutex());
2467            stack.takeBlockFrom(s_markingStack);
2468        }
2469    }
2470    {
2471        MutexLocker locker(markingMutex());
2472        if (!--(*runningMarkingThreads))
2473            markingCondition().signal();
2474    }
2475}
2476
2477void Heap::processMarkingStackOnMultipleThreads()
2478{
2479    int runningMarkingThreads = s_markingThreads->size() + 1;
2480
2481    for (size_t i = 0; i < s_markingThreads->size(); ++i)
2482        s_markingThreads->at(i)->postTask(new Task(WTF::bind(Heap::processMarkingStackEntries, &runningMarkingThreads)));
2483
2484    processMarkingStackEntries(&runningMarkingThreads);
2485
2486    // Wait for the other threads to finish their part of marking.
2487    MutexLocker locker(markingMutex());
2488    while (runningMarkingThreads)
2489        markingCondition().wait(markingMutex());
2490}
2491
2492void Heap::processMarkingStackInParallel()
2493{
2494    static const size_t sizeOfStackForParallelMarking = 2 * CallbackStack::blockSize;
2495    // Ephemeron fixed point loop run on the garbage collecting thread.
2496    do {
2497        // Iteratively mark all objects that are reachable from the objects
2498        // currently pushed onto the marking stack. Do so in parallel if there
2499        // are multiple blocks on the global marking stack.
2500        if (s_markingStack->sizeExceeds(sizeOfStackForParallelMarking)) {
2501            processMarkingStackOnMultipleThreads();
2502        } else {
2503            TRACE_EVENT0("blink_gc", "Heap::processMarkingStackSingleThreaded");
2504            while (popAndInvokeTraceCallback<GlobalMarking>(s_markingStack, s_markingVisitor)) { }
2505        }
2506
2507        // Mark any strong pointers that have now become reachable in ephemeron
2508        // maps.
2509        TRACE_EVENT0("blink_gc", "Heap::processEphemeronStack");
2510        s_ephemeronStack->invokeEphemeronCallbacks(s_markingVisitor);
2511
2512        // Rerun loop if ephemeron processing queued more objects for tracing.
2513    } while (!s_markingStack->isEmpty());
2514}
2515
2516template<CallbackInvocationMode Mode>
2517void Heap::processMarkingStack()
2518{
2519    // Ephemeron fixed point loop.
2520    do {
2521        // Iteratively mark all objects that are reachable from the objects
2522        // currently pushed onto the marking stack. If Mode is ThreadLocalMarking
2523        // don't continue tracing if the trace hits an object on another thread's
2524        // heap.
2525        TRACE_EVENT0("blink_gc", "Heap::processMarkingStackSingleThreaded");
2526        while (popAndInvokeTraceCallback<Mode>(s_markingStack, s_markingVisitor)) { }
2527
2528        // Mark any strong pointers that have now become reachable in ephemeron
2529        // maps.
2530        TRACE_EVENT0("blink_gc", "Heap::processEphemeronStack");
2531        s_ephemeronStack->invokeEphemeronCallbacks(s_markingVisitor);
2532
2533        // Rerun loop if ephemeron processing queued more objects for tracing.
2534    } while (!s_markingStack->isEmpty());
2535}
2536
2537void Heap::postMarkingProcessing()
2538{
2539    TRACE_EVENT0("blink_gc", "Heap::postMarkingProcessing");
2540    // Call post-marking callbacks including:
2541    // 1. the ephemeronIterationDone callbacks on weak tables to do cleanup
2542    //    (specifically to clear the queued bits for weak hash tables), and
2543    // 2. the markNoTracing callbacks on collection backings to mark them
2544    //    if they are only reachable from their front objects.
2545    while (popAndInvokePostMarkingCallback(s_markingVisitor)) { }
2546
2547    s_ephemeronStack->clear();
2548
2549    // Post-marking callbacks should not trace any objects and
2550    // therefore the marking stack should be empty after the
2551    // post-marking callbacks.
2552    ASSERT(s_markingStack->isEmpty());
2553}
2554
2555void Heap::globalWeakProcessing()
2556{
2557    TRACE_EVENT0("blink_gc", "Heap::globalWeakProcessing");
2558    // Call weak callbacks on objects that may now be pointing to dead
2559    // objects.
2560    while (popAndInvokeWeakPointerCallback(s_markingVisitor)) { }
2561
2562    // It is not permitted to trace pointers of live objects in the weak
2563    // callback phase, so the marking stack should still be empty here.
2564    ASSERT(s_markingStack->isEmpty());
2565}
2566
2567void Heap::collectAllGarbage()
2568{
2569    // FIXME: oilpan: we should perform a single GC and everything
2570    // should die. Unfortunately it is not the case for all objects
2571    // because the hierarchy was not completely moved to the heap and
2572    // some heap allocated objects own objects that contain persistents
2573    // pointing to other heap allocated objects.
2574    for (int i = 0; i < 5; i++)
2575        collectGarbage(ThreadState::NoHeapPointersOnStack, ThreadState::ForcedGC);
2576}
2577
2578void Heap::setForcePreciseGCForTesting()
2579{
2580    ThreadState::current()->setForcePreciseGCForTesting(true);
2581}
2582
2583template<typename Header>
2584void ThreadHeap<Header>::prepareHeapForTermination()
2585{
2586    for (HeapPage<Header>* page = m_firstPage; page; page = page->next()) {
2587        page->setTerminating();
2588    }
2589    for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current; current = current->next()) {
2590        current->setTerminating();
2591    }
2592}
2593
2594template<typename Header>
2595BaseHeap* ThreadHeap<Header>::split(int numberOfNormalPages)
2596{
2597    // Create a new split off thread heap containing
2598    // |numberOfNormalPages| of the pages of this ThreadHeap for
2599    // parallel sweeping. The split off thread heap will be merged
2600    // with this heap at the end of sweeping and the temporary
2601    // ThreadHeap object will be deallocated after the merge.
2602    ASSERT(numberOfNormalPages > 0);
2603    ThreadHeap<Header>* splitOff = new ThreadHeap(m_threadState, m_index);
2604    HeapPage<Header>* splitPoint = m_firstPage;
2605    for (int i = 1; i < numberOfNormalPages; i++)
2606        splitPoint = splitPoint->next();
2607    splitOff->m_firstPage = m_firstPage;
2608    m_firstPage = splitPoint->m_next;
2609    splitOff->m_mergePoint = splitPoint;
2610    splitOff->m_numberOfNormalPages = numberOfNormalPages;
2611    m_numberOfNormalPages -= numberOfNormalPages;
2612    splitPoint->m_next = 0;
2613    return splitOff;
2614}
2615
2616template<typename Header>
2617void ThreadHeap<Header>::merge(BaseHeap* splitOffBase)
2618{
2619    ThreadHeap<Header>* splitOff = static_cast<ThreadHeap<Header>*>(splitOffBase);
2620    // If the mergePoint is zero all split off pages became empty in
2621    // this round and we don't have to merge. There are no pages and
2622    // nothing on the freelists.
2623    ASSERT(splitOff->m_mergePoint || splitOff->m_numberOfNormalPages == 0);
2624    if (splitOff->m_mergePoint) {
2625        // Link the split off pages into the beginning of the list again.
2626        splitOff->m_mergePoint->m_next = m_firstPage;
2627        m_firstPage = splitOff->m_firstPage;
2628        m_numberOfNormalPages += splitOff->m_numberOfNormalPages;
2629        splitOff->m_firstPage = 0;
2630        // Merge free lists.
2631        for (size_t i = 0; i < blinkPageSizeLog2; i++) {
2632            if (!m_freeLists[i]) {
2633                m_freeLists[i] = splitOff->m_freeLists[i];
2634            } else if (splitOff->m_freeLists[i]) {
2635                m_lastFreeListEntries[i]->append(splitOff->m_freeLists[i]);
2636                m_lastFreeListEntries[i] = splitOff->m_lastFreeListEntries[i];
2637            }
2638        }
2639    }
2640    delete splitOffBase;
2641}
2642
2643void Heap::getHeapSpaceSize(uint64_t* objectSpaceSize, uint64_t* allocatedSpaceSize)
2644{
2645    *objectSpaceSize = 0;
2646    *allocatedSpaceSize = 0;
2647    ASSERT(ThreadState::isAnyThreadInGC());
2648    ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads();
2649    typedef ThreadState::AttachedThreadStateSet::iterator ThreadStateIterator;
2650    for (ThreadStateIterator it = threads.begin(), end = threads.end(); it != end; ++it) {
2651        *objectSpaceSize += (*it)->stats().totalObjectSpace();
2652        *allocatedSpaceSize += (*it)->stats().totalAllocatedSpace();
2653    }
2654}
2655
2656void Heap::getStats(HeapStats* stats)
2657{
2658    stats->clear();
2659    ASSERT(ThreadState::isAnyThreadInGC());
2660    ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads();
2661    typedef ThreadState::AttachedThreadStateSet::iterator ThreadStateIterator;
2662    for (ThreadStateIterator it = threads.begin(), end = threads.end(); it != end; ++it) {
2663        HeapStats temp;
2664        (*it)->getStats(temp);
2665        stats->add(&temp);
2666    }
2667}
2668
2669#if ENABLE(ASSERT)
2670bool Heap::isConsistentForSweeping()
2671{
2672    ASSERT(ThreadState::isAnyThreadInGC());
2673    ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads();
2674    for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it) {
2675        if (!(*it)->isConsistentForSweeping())
2676            return false;
2677    }
2678    return true;
2679}
2680#endif
2681
2682void Heap::makeConsistentForSweeping()
2683{
2684    ASSERT(ThreadState::isAnyThreadInGC());
2685    ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads();
2686    for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it)
2687        (*it)->makeConsistentForSweeping();
2688}
2689
2690void HeapAllocator::backingFree(void* address)
2691{
2692    if (!address || ThreadState::isAnyThreadInGC())
2693        return;
2694
2695    ThreadState* state = ThreadState::current();
2696    if (state->isSweepInProgress())
2697        return;
2698
2699    // Don't promptly free large objects because their page is never reused
2700    // and don't free backings allocated on other threads.
2701    BaseHeapPage* page = pageHeaderFromObject(address);
2702    if (page->isLargeObject() || page->threadState() != state)
2703        return;
2704
2705    typedef HeapIndexTrait<CollectionBackingHeap> HeapTraits;
2706    typedef HeapTraits::HeapType HeapType;
2707    typedef HeapTraits::HeaderType HeaderType;
2708
2709    HeaderType* header = HeaderType::fromPayload(address);
2710    header->checkHeader();
2711
2712    const GCInfo* gcInfo = header->gcInfo();
2713    int heapIndex = HeapTraits::index(gcInfo->hasFinalizer());
2714    HeapType* heap = static_cast<HeapType*>(state->heap(heapIndex));
2715    heap->promptlyFreeObject(header);
2716}
2717
2718// Force template instantiations for the types that we need.
2719template class HeapPage<FinalizedHeapObjectHeader>;
2720template class HeapPage<HeapObjectHeader>;
2721template class ThreadHeap<FinalizedHeapObjectHeader>;
2722template class ThreadHeap<HeapObjectHeader>;
2723
2724Visitor* Heap::s_markingVisitor;
2725Vector<OwnPtr<blink::WebThread> >* Heap::s_markingThreads;
2726CallbackStack* Heap::s_markingStack;
2727CallbackStack* Heap::s_postMarkingCallbackStack;
2728CallbackStack* Heap::s_weakCallbackStack;
2729CallbackStack* Heap::s_ephemeronStack;
2730HeapDoesNotContainCache* Heap::s_heapDoesNotContainCache;
2731bool Heap::s_shutdownCalled = false;
2732bool Heap::s_lastGCWasConservative = false;
2733FreePagePool* Heap::s_freePagePool;
2734OrphanedPagePool* Heap::s_orphanedPagePool;
2735}
2736