Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(527)

Unified Diff: sky/engine/platform/heap/Heap.h

Issue 681113004: Remove Heap.h (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: sky/engine/platform/heap/Heap.h
diff --git a/sky/engine/platform/heap/Heap.h b/sky/engine/platform/heap/Heap.h
deleted file mode 100644
index 8acbc707079e38ba8792b6f38a5e8541b71cd467..0000000000000000000000000000000000000000
--- a/sky/engine/platform/heap/Heap.h
+++ /dev/null
@@ -1,1588 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef Heap_h
-#define Heap_h
-
-#include "platform/PlatformExport.h"
-#include "platform/heap/AddressSanitizer.h"
-#include "platform/heap/ThreadState.h"
-#include "platform/heap/Visitor.h"
-#include "public/platform/WebThread.h"
-#include "wtf/Assertions.h"
-#include "wtf/HashCountedSet.h"
-#include "wtf/LinkedHashSet.h"
-#include "wtf/ListHashSet.h"
-#include "wtf/OwnPtr.h"
-#include "wtf/PassRefPtr.h"
-#include "wtf/ThreadSafeRefCounted.h"
-
-#include <stdint.h>
-
-namespace blink {
-
-const size_t blinkPageSizeLog2 = 17;
-const size_t blinkPageSize = 1 << blinkPageSizeLog2;
-const size_t blinkPageOffsetMask = blinkPageSize - 1;
-const size_t blinkPageBaseMask = ~blinkPageOffsetMask;
-
-// We allocate pages at random addresses but in groups of
-// blinkPagesPerRegion at a given random address. We group pages to
-// not spread out too much over the address space which would blow
-// away the page tables and lead to bad performance.
-const size_t blinkPagesPerRegion = 10;
-
-// Double precision floats are more efficient when 8 byte aligned, so we 8 byte
-// align all allocations even on 32 bit.
-const size_t allocationGranularity = 8;
-const size_t allocationMask = allocationGranularity - 1;
-const size_t objectStartBitMapSize = (blinkPageSize + ((8 * allocationGranularity) - 1)) / (8 * allocationGranularity);
-const size_t reservedForObjectBitMap = ((objectStartBitMapSize + allocationMask) & ~allocationMask);
-const size_t maxHeapObjectSizeLog2 = 27;
-const size_t maxHeapObjectSize = 1 << maxHeapObjectSizeLog2;
-
-const size_t markBitMask = 1;
-const size_t freeListMask = 2;
-// The dead bit is used for objects that have gone through a GC marking, but did
-// not get swept before a new GC started. In that case we set the dead bit on
-// objects that were not marked in the previous GC to ensure we are not tracing
-// them via a conservatively found pointer. Tracing dead objects could lead to
-// tracing of already finalized objects in another thread's heap which is a
-// use-after-free situation.
-const size_t deadBitMask = 4;
-// On free-list entries we reuse the dead bit to distinguish a normal free-list
-// entry from one that has been promptly freed.
-const size_t promptlyFreedMask = freeListMask | deadBitMask;
-#if ENABLE(GC_PROFILE_HEAP)
-const size_t heapObjectGenerations = 8;
-const size_t maxHeapObjectAge = heapObjectGenerations - 1;
-const size_t heapObjectAgeMask = ~(maxHeapObjectSize - 1);
-const size_t sizeMask = ~heapObjectAgeMask & ~static_cast<size_t>(7);
-#else
-const size_t sizeMask = ~static_cast<size_t>(7);
-#endif
-const uint8_t freelistZapValue = 42;
-const uint8_t finalizedZapValue = 24;
-// The orphaned zap value must be zero in the lowest bits to allow for using
-// the mark bit when tracing.
-const uint8_t orphanedZapValue = 240;
-
-const int numberOfMarkingThreads = 2;
-
-const int numberOfPagesToConsiderForCoalescing = 100;
-
-enum CallbackInvocationMode {
- GlobalMarking,
- ThreadLocalMarking,
- PostMarking,
- WeaknessProcessing,
-};
-
-class HeapStats;
-class PageMemory;
-template<ThreadAffinity affinity> class ThreadLocalPersistents;
-template<typename T, typename RootsAccessor = ThreadLocalPersistents<ThreadingTrait<T>::Affinity > > class Persistent;
-
-#if ENABLE(GC_PROFILE_HEAP)
-class TracedValue;
-#endif
-
-PLATFORM_EXPORT size_t osPageSize();
-
-// Blink heap pages are set up with a guard page before and after the
-// payload.
-inline size_t blinkPagePayloadSize()
-{
- return blinkPageSize - 2 * osPageSize();
-}
-
-// Blink heap pages are aligned to the Blink heap page size.
-// Therefore, the start of a Blink page can be obtained by
-// rounding down to the Blink page size.
-inline Address roundToBlinkPageStart(Address address)
-{
- return reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address) & blinkPageBaseMask);
-}
-
-inline Address roundToBlinkPageEnd(Address address)
-{
- return reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address - 1) & blinkPageBaseMask) + blinkPageSize;
-}
-
-// Compute the amount of padding we have to add to a header to make
-// the size of the header plus the padding a multiple of 8 bytes.
-template<typename Header>
-inline size_t headerPadding()
-{
- return (allocationGranularity - (sizeof(Header) % allocationGranularity)) % allocationGranularity;
-}
-
-// Masks an address down to the enclosing blink page base address.
-inline Address blinkPageAddress(Address address)
-{
- return reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address) & blinkPageBaseMask);
-}
-
-#if ENABLE(ASSERT)
-
-// Sanity check for a page header address: the address of the page
-// header should be OS page size away from being Blink page size
-// aligned.
-inline bool isPageHeaderAddress(Address address)
-{
- return !((reinterpret_cast<uintptr_t>(address) & blinkPageOffsetMask) - osPageSize());
-}
-#endif
-
-// Mask an address down to the enclosing oilpan heap base page.
-// All oilpan heap pages are aligned at blinkPageBase plus an OS page size.
-// FIXME: Remove PLATFORM_EXPORT once we get a proper public interface to our typed heaps.
-// This is only exported to enable tests in HeapTest.cpp.
-PLATFORM_EXPORT inline BaseHeapPage* pageHeaderFromObject(const void* object)
-{
- Address address = reinterpret_cast<Address>(const_cast<void*>(object));
- return reinterpret_cast<BaseHeapPage*>(blinkPageAddress(address) + osPageSize());
-}
-
-// Large allocations are allocated as separate objects and linked in a
-// list.
-//
-// In order to use the same memory allocation routines for everything
-// allocated in the heap, large objects are considered heap pages
-// containing only one object.
-//
-// The layout of a large heap object is as follows:
-//
-// | BaseHeapPage | next pointer | FinalizedHeapObjectHeader or HeapObjectHeader | payload |
-template<typename Header>
-class LargeHeapObject : public BaseHeapPage {
-public:
- LargeHeapObject(PageMemory* storage, const GCInfo* gcInfo, ThreadState* state) : BaseHeapPage(storage, gcInfo, state)
- {
- COMPILE_ASSERT(!(sizeof(LargeHeapObject<Header>) & allocationMask), large_heap_object_header_misaligned);
- }
-
- virtual void checkAndMarkPointer(Visitor*, Address) override;
- virtual bool isLargeObject() override { return true; }
-
-#if ENABLE(GC_PROFILE_MARKING)
- virtual const GCInfo* findGCInfo(Address address)
- {
- if (!objectContains(address))
- return 0;
- return gcInfo();
- }
-#endif
-
-#if ENABLE(GC_PROFILE_HEAP)
- void snapshot(TracedValue*, ThreadState::SnapshotInfo*);
-#endif
-
- void link(LargeHeapObject<Header>** previousNext)
- {
- m_next = *previousNext;
- *previousNext = this;
- }
-
- void unlink(LargeHeapObject<Header>** previousNext)
- {
- *previousNext = m_next;
- }
-
- // The LargeHeapObject pseudo-page contains one actual object. Determine
- // whether the pointer is within that object.
- bool objectContains(Address object)
- {
- return (payload() <= object) && (object < address() + size());
- }
-
- // Returns true for any address that is on one of the pages that this
- // large object uses. That ensures that we can use a negative result to
- // populate the negative page cache.
- virtual bool contains(Address object) override
- {
- return roundToBlinkPageStart(address()) <= object && object < roundToBlinkPageEnd(address() + size());
- }
-
- LargeHeapObject<Header>* next()
- {
- return m_next;
- }
-
- size_t size()
- {
- return heapObjectHeader()->size() + sizeof(LargeHeapObject<Header>) + headerPadding<Header>();
- }
-
- Address payload() { return heapObjectHeader()->payload(); }
- size_t payloadSize() { return heapObjectHeader()->payloadSize(); }
-
- Header* heapObjectHeader()
- {
- Address headerAddress = address() + sizeof(LargeHeapObject<Header>) + headerPadding<Header>();
- return reinterpret_cast<Header*>(headerAddress);
- }
-
- bool isMarked();
- void unmark();
- void getStats(HeapStats&);
- void mark(Visitor*);
- void finalize();
- void setDeadMark();
- virtual void markOrphaned()
- {
- // Zap the payload with a recognizable value to detect any incorrect
- // cross thread pointer usage.
- memset(payload(), orphanedZapValue, payloadSize());
- BaseHeapPage::markOrphaned();
- }
-
-private:
- friend class ThreadHeap<Header>;
-
- LargeHeapObject<Header>* m_next;
-};
-
-// The BasicObjectHeader is the minimal object header. It is used when
-// encountering heap space of size allocationGranularity to mark it as
-// as freelist entry.
-class PLATFORM_EXPORT BasicObjectHeader {
-public:
- NO_SANITIZE_ADDRESS
- explicit BasicObjectHeader(size_t encodedSize)
- : m_size(encodedSize) { }
-
- static size_t freeListEncodedSize(size_t size) { return size | freeListMask; }
-
- NO_SANITIZE_ADDRESS
- bool isFree() { return m_size & freeListMask; }
-
- NO_SANITIZE_ADDRESS
- bool isPromptlyFreed() { return (m_size & promptlyFreedMask) == promptlyFreedMask; }
-
- NO_SANITIZE_ADDRESS
- void markPromptlyFreed() { m_size |= promptlyFreedMask; }
-
- NO_SANITIZE_ADDRESS
- size_t size() const { return m_size & sizeMask; }
-
-#if ENABLE(GC_PROFILE_HEAP)
- NO_SANITIZE_ADDRESS
- size_t encodedSize() const { return m_size; }
-
- NO_SANITIZE_ADDRESS
- size_t age() const { return m_size >> maxHeapObjectSizeLog2; }
-
- NO_SANITIZE_ADDRESS
- void incAge()
- {
- size_t current = age();
- if (current < maxHeapObjectAge)
- m_size = ((current + 1) << maxHeapObjectSizeLog2) | (m_size & ~heapObjectAgeMask);
- }
-#endif
-
-protected:
- volatile unsigned m_size;
-};
-
-// Our heap object layout is layered with the HeapObjectHeader closest
-// to the payload, this can be wrapped in a FinalizedObjectHeader if the
-// object is on the GeneralHeap and not on a specific TypedHeap.
-// Finally if the object is a large object (> blinkPageSize/2) then it is
-// wrapped with a LargeObjectHeader.
-//
-// Object memory layout:
-// [ LargeObjectHeader | ] [ FinalizedObjectHeader | ] HeapObjectHeader | payload
-// The [ ] notation denotes that the LargeObjectHeader and the FinalizedObjectHeader
-// are independently optional.
-class PLATFORM_EXPORT HeapObjectHeader : public BasicObjectHeader {
-public:
- NO_SANITIZE_ADDRESS
- explicit HeapObjectHeader(size_t encodedSize)
- : BasicObjectHeader(encodedSize)
-#if ENABLE(ASSERT)
- , m_magic(magic)
-#endif
- { }
-
- NO_SANITIZE_ADDRESS
- HeapObjectHeader(size_t encodedSize, const GCInfo*)
- : BasicObjectHeader(encodedSize)
-#if ENABLE(ASSERT)
- , m_magic(magic)
-#endif
- { }
-
- inline void checkHeader() const;
- inline bool isMarked() const;
-
- inline void mark();
- inline void unmark();
-
- inline const GCInfo* gcInfo() { return 0; }
-
- inline Address payload();
- inline size_t payloadSize();
- inline Address payloadEnd();
-
- inline void setDeadMark();
- inline void clearDeadMark();
- inline bool hasDeadMark() const;
-
- // Zap magic number with a new magic number that means there was once an
- // object allocated here, but it was freed because nobody marked it during
- // GC.
- void zapMagic();
-
- static void finalize(const GCInfo*, Address, size_t);
- static HeapObjectHeader* fromPayload(const void*);
-
- static const intptr_t magic = 0xc0de247;
- static const intptr_t zappedMagic = 0xC0DEdead;
- // The zap value for vtables should be < 4K to ensure it cannot be
- // used for dispatch.
- static const intptr_t zappedVTable = 0xd0d;
-
-private:
-#if ENABLE(ASSERT)
- intptr_t m_magic;
-#endif
-};
-
-const size_t objectHeaderSize = sizeof(HeapObjectHeader);
-
-// Each object on the GeneralHeap needs to carry a pointer to its
-// own GCInfo structure for tracing and potential finalization.
-class PLATFORM_EXPORT FinalizedHeapObjectHeader : public HeapObjectHeader {
-public:
- NO_SANITIZE_ADDRESS
- FinalizedHeapObjectHeader(size_t encodedSize, const GCInfo* gcInfo)
- : HeapObjectHeader(encodedSize)
- , m_gcInfo(gcInfo)
- {
- }
-
- inline Address payload();
- inline size_t payloadSize();
-
- NO_SANITIZE_ADDRESS
- const GCInfo* gcInfo() { return m_gcInfo; }
-
- NO_SANITIZE_ADDRESS
- TraceCallback traceCallback() { return m_gcInfo->m_trace; }
-
- void finalize();
-
- NO_SANITIZE_ADDRESS
- inline bool hasFinalizer() { return m_gcInfo->hasFinalizer(); }
-
- static FinalizedHeapObjectHeader* fromPayload(const void*);
-
- NO_SANITIZE_ADDRESS
- bool hasVTable() { return m_gcInfo->hasVTable(); }
-
-private:
- const GCInfo* m_gcInfo;
-};
-
-const size_t finalizedHeaderSize = sizeof(FinalizedHeapObjectHeader);
-
-class FreeListEntry : public HeapObjectHeader {
-public:
- NO_SANITIZE_ADDRESS
- explicit FreeListEntry(size_t size)
- : HeapObjectHeader(freeListEncodedSize(size))
- , m_next(0)
- {
-#if ENABLE(ASSERT) && !defined(ADDRESS_SANITIZER)
- // Zap free area with asterisks, aka 0x2a2a2a2a.
- // For ASan don't zap since we keep accounting in the freelist entry.
- for (size_t i = sizeof(*this); i < size; i++)
- reinterpret_cast<Address>(this)[i] = freelistZapValue;
- ASSERT(size >= objectHeaderSize);
- zapMagic();
-#endif
- }
-
- Address address() { return reinterpret_cast<Address>(this); }
-
- NO_SANITIZE_ADDRESS
- void unlink(FreeListEntry** prevNext)
- {
- *prevNext = m_next;
- m_next = 0;
- }
-
- NO_SANITIZE_ADDRESS
- void link(FreeListEntry** prevNext)
- {
- m_next = *prevNext;
- *prevNext = this;
- }
-
- NO_SANITIZE_ADDRESS
- FreeListEntry* next() const { return m_next; }
-
- NO_SANITIZE_ADDRESS
- void append(FreeListEntry* next)
- {
- ASSERT(!m_next);
- m_next = next;
- }
-
-#if defined(ADDRESS_SANITIZER)
- NO_SANITIZE_ADDRESS
- bool shouldAddToFreeList()
- {
- // Init if not already magic.
- if ((m_asanMagic & ~asanDeferMemoryReuseMask) != asanMagic) {
- m_asanMagic = asanMagic | asanDeferMemoryReuseCount;
- return false;
- }
- // Decrement if count part of asanMagic > 0.
- if (m_asanMagic & asanDeferMemoryReuseMask)
- m_asanMagic--;
- return !(m_asanMagic & asanDeferMemoryReuseMask);
- }
-#endif
-
-private:
- FreeListEntry* m_next;
-#if defined(ADDRESS_SANITIZER)
- unsigned m_asanMagic;
-#endif
-};
-
-// Representation of Blink heap pages.
-//
-// Pages are specialized on the type of header on the object they
-// contain. If a heap page only contains a certain type of object all
-// of the objects will have the same GCInfo pointer and therefore that
-// pointer can be stored in the HeapPage instead of in the header of
-// each object. In that case objects have only a HeapObjectHeader and
-// not a FinalizedHeapObjectHeader saving a word per object.
-template<typename Header>
-class HeapPage : public BaseHeapPage {
-public:
- HeapPage(PageMemory*, ThreadHeap<Header>*, const GCInfo*);
-
- void link(HeapPage**);
- static void unlink(ThreadHeap<Header>*, HeapPage*, HeapPage**);
-
- bool isEmpty();
-
- // Returns true for the whole blinkPageSize page that the page is on, even
- // for the header, and the unmapped guard page at the start. That ensures
- // the result can be used to populate the negative page cache.
- virtual bool contains(Address addr) override
- {
- Address blinkPageStart = roundToBlinkPageStart(address());
- ASSERT(blinkPageStart == address() - osPageSize()); // Page is at aligned address plus guard page size.
- return blinkPageStart <= addr && addr < blinkPageStart + blinkPageSize;
- }
-
- HeapPage* next() { return m_next; }
-
- Address payload()
- {
- return address() + sizeof(*this) + headerPadding<Header>();
- }
-
- static size_t payloadSize()
- {
- return (blinkPagePayloadSize() - sizeof(HeapPage) - headerPadding<Header>()) & ~allocationMask;
- }
-
- Address end() { return payload() + payloadSize(); }
-
- void getStats(HeapStats&);
- void clearLiveAndMarkDead();
- void sweep(HeapStats*, ThreadHeap<Header>*);
- void clearObjectStartBitMap();
- void finalize(Header*);
- virtual void checkAndMarkPointer(Visitor*, Address) override;
-#if ENABLE(GC_PROFILE_MARKING)
- const GCInfo* findGCInfo(Address) override;
-#endif
-#if ENABLE(GC_PROFILE_HEAP)
- virtual void snapshot(TracedValue*, ThreadState::SnapshotInfo*);
-#endif
-
-#if defined(ADDRESS_SANITIZER)
- void poisonUnmarkedObjects();
-#endif
- NO_SANITIZE_ADDRESS
- virtual void markOrphaned()
- {
- // Zap the payload with a recognizable value to detect any incorrect
- // cross thread pointer usage.
-#if defined(ADDRESS_SANITIZER)
- // Don't use memset when running with ASan since this needs to zap
- // poisoned memory as well and the NO_SANITIZE_ADDRESS annotation
- // only works for code in this method and not for calls to memset.
- for (Address current = payload(); current < payload() + payloadSize(); ++current)
- *current = orphanedZapValue;
-#else
- memset(payload(), orphanedZapValue, payloadSize());
-#endif
- BaseHeapPage::markOrphaned();
- }
-
-protected:
- Header* findHeaderFromAddress(Address);
- void populateObjectStartBitMap();
- bool isObjectStartBitMapComputed() { return m_objectStartBitMapComputed; }
- TraceCallback traceCallback(Header*);
- bool hasVTable(Header*);
-
- intptr_t padding() const { return m_padding; }
-
- HeapPage<Header>* m_next;
- intptr_t m_padding; // Preserve 8-byte alignment on 32-bit systems.
- bool m_objectStartBitMapComputed;
- uint8_t m_objectStartBitMap[reservedForObjectBitMap];
-
- friend class ThreadHeap<Header>;
-};
-
-class AddressEntry {
-public:
- AddressEntry() : m_address(0) { }
-
- explicit AddressEntry(Address address) : m_address(address) { }
-
- Address address() const { return m_address; }
-
-private:
- Address m_address;
-};
-
-class PositiveEntry : public AddressEntry {
-public:
- PositiveEntry()
- : AddressEntry()
- , m_containingPage(0)
- {
- }
-
- PositiveEntry(Address address, BaseHeapPage* containingPage)
- : AddressEntry(address)
- , m_containingPage(containingPage)
- {
- }
-
- BaseHeapPage* result() const { return m_containingPage; }
-
- typedef BaseHeapPage* LookupResult;
-
-private:
- BaseHeapPage* m_containingPage;
-};
-
-class NegativeEntry : public AddressEntry {
-public:
- NegativeEntry() : AddressEntry() { }
-
- NegativeEntry(Address address, bool) : AddressEntry(address) { }
-
- bool result() const { return true; }
-
- typedef bool LookupResult;
-};
-
-// A HeapExtentCache provides a fast way of taking an arbitrary
-// pointer-sized word, and determining whether it can be interpreted
-// as a pointer to an area that is managed by the garbage collected
-// Blink heap. There is a cache of 'pages' that have previously been
-// determined to be wholly inside the heap. The size of these pages must be
-// smaller than the allocation alignment of the heap pages. We determine
-// on-heap-ness by rounding down the pointer to the nearest page and looking up
-// the page in the cache. If there is a miss in the cache we can ask the heap
-// to determine the status of the pointer by iterating over all of the heap.
-// The result is then cached in the two-way associative page cache.
-//
-// A HeapContainsCache is a positive cache. Therefore, it must be flushed when
-// memory is removed from the Blink heap. The HeapDoesNotContainCache is a
-// negative cache, so it must be flushed when memory is added to the heap.
-template<typename Entry>
-class HeapExtentCache {
-public:
- HeapExtentCache()
- : m_entries(adoptArrayPtr(new Entry[HeapExtentCache::numberOfEntries]))
- , m_hasEntries(false)
- {
- }
-
- void flush();
- bool contains(Address);
- bool isEmpty() { return !m_hasEntries; }
-
- // Perform a lookup in the cache.
- //
- // If lookup returns null/false the argument address was not found in
- // the cache and it is unknown if the address is in the Blink
- // heap.
- //
- // If lookup returns true/a page, the argument address was found in the
- // cache. For the HeapContainsCache this means the address is in the heap.
- // For the HeapDoesNotContainCache this means the address is not in the
- // heap.
- PLATFORM_EXPORT typename Entry::LookupResult lookup(Address);
-
- // Add an entry to the cache.
- PLATFORM_EXPORT void addEntry(Address, typename Entry::LookupResult);
-
-private:
- static const int numberOfEntriesLog2 = 12;
- static const int numberOfEntries = 1 << numberOfEntriesLog2;
-
- static size_t hash(Address);
-
- WTF::OwnPtr<Entry[]> m_entries;
- bool m_hasEntries;
-
- friend class ThreadState;
-};
-
-// Normally these would be typedefs instead of subclasses, but that makes them
-// very hard to forward declare.
-class HeapContainsCache : public HeapExtentCache<PositiveEntry> {
-public:
- BaseHeapPage* lookup(Address);
- void addEntry(Address, BaseHeapPage*);
-};
-
-class HeapDoesNotContainCache : public HeapExtentCache<NegativeEntry> { };
-
-template<typename DataType>
-class PagePool {
-protected:
- PagePool();
-
- class PoolEntry {
- public:
- PoolEntry(DataType* data, PoolEntry* next)
- : data(data)
- , next(next)
- { }
-
- DataType* data;
- PoolEntry* next;
- };
-
- PoolEntry* m_pool[NumberOfHeaps];
-};
-
-// Once pages have been used for one type of thread heap they will never be
-// reused for another type of thread heap. Instead of unmapping, we add the
-// pages to a pool of pages to be reused later by a thread heap of the same
-// type. This is done as a security feature to avoid type confusion. The
-// heaps are type segregated by having separate thread heaps for different
-// types of objects. Holding on to pages ensures that the same virtual address
-// space cannot be used for objects of another type than the type contained
-// in this page to begin with.
-class FreePagePool : public PagePool<PageMemory> {
-public:
- ~FreePagePool();
- void addFreePage(int, PageMemory*);
- PageMemory* takeFreePage(int);
-
-private:
- Mutex m_mutex[NumberOfHeaps];
-};
-
-class OrphanedPagePool : public PagePool<BaseHeapPage> {
-public:
- ~OrphanedPagePool();
- void addOrphanedPage(int, BaseHeapPage*);
- void decommitOrphanedPages();
-#if ENABLE(ASSERT)
- bool contains(void*);
-#endif
-private:
- void clearMemory(PageMemory*);
-};
-
-// The CallbackStack contains all the visitor callbacks used to trace and mark
-// objects. A specific CallbackStack instance contains at most bufferSize elements.
-// If more space is needed a new CallbackStack instance is created and chained
-// together with the former instance. I.e. a logical CallbackStack can be made of
-// multiple chained CallbackStack object instances.
-// There are two logical callback stacks. One containing all the marking callbacks and
-// one containing the weak pointer callbacks.
-class CallbackStack {
-public:
- CallbackStack(CallbackStack** first)
- : m_limit(&(m_buffer[bufferSize]))
- , m_current(&(m_buffer[0]))
- , m_next(*first)
- {
-#if ENABLE(ASSERT)
- clearUnused();
-#endif
- *first = this;
- }
-
- ~CallbackStack();
- void clearUnused();
-
- bool isEmpty();
-
- CallbackStack* takeCallbacks(CallbackStack** first);
-
- class Item {
- public:
- Item() { }
- Item(void* object, VisitorCallback callback)
- : m_object(object)
- , m_callback(callback)
- {
- }
- void* object() { return m_object; }
- VisitorCallback callback() { return m_callback; }
-
- private:
- void* m_object;
- VisitorCallback m_callback;
- };
-
- static void init(CallbackStack** first);
- static void shutdown(CallbackStack** first);
- static void clear(CallbackStack** first)
- {
- if (!(*first)->isEmpty()) {
- shutdown(first);
- init(first);
- }
- }
- template<CallbackInvocationMode Mode> bool popAndInvokeCallback(CallbackStack** first, Visitor*);
- static void invokeCallbacks(CallbackStack** first, Visitor*);
-
- Item* allocateEntry(CallbackStack** first)
- {
- if (m_current < m_limit)
- return m_current++;
- return (new CallbackStack(first))->allocateEntry(first);
- }
-
-#if ENABLE(ASSERT)
- bool hasCallbackForObject(const void*);
-#endif
-
- bool numberOfBlocksExceeds(int blocks)
- {
- CallbackStack* current = this;
- for (int i = 0; i < blocks; ++i) {
- if (!current->m_next)
- return false;
- current = current->m_next;
- }
- return true;
- }
-
-private:
- void invokeOldestCallbacks(Visitor*);
- bool currentBlockIsEmpty() { return m_current == &(m_buffer[0]); }
-
- static const size_t bufferSize = 200;
- Item m_buffer[bufferSize];
- Item* m_limit;
- Item* m_current;
- CallbackStack* m_next;
-};
-
-// Non-template super class used to pass a heap around to other classes.
-class BaseHeap {
-public:
- virtual ~BaseHeap() { }
- virtual void cleanupPages() = 0;
-
- // Find the page in this thread heap containing the given
- // address. Returns 0 if the address is not contained in any
- // page in this thread heap.
- virtual BaseHeapPage* heapPageFromAddress(Address) = 0;
-
-#if ENABLE(GC_PROFILE_MARKING)
- virtual const GCInfo* findGCInfoOfLargeHeapObject(Address) = 0;
-#endif
-
-#if ENABLE(GC_PROFILE_HEAP)
- virtual void snapshot(TracedValue*, ThreadState::SnapshotInfo*) = 0;
-#endif
-
- // Sweep this part of the Blink heap. This finalizes dead objects
- // and builds freelists for all the unused memory.
- virtual void sweep(HeapStats*) = 0;
- virtual void postSweepProcessing() = 0;
-
- virtual void clearFreeLists() = 0;
- virtual void clearLiveAndMarkDead() = 0;
-
- virtual void makeConsistentForSweeping() = 0;
-
-#if ENABLE(ASSERT)
- virtual bool isConsistentForSweeping() = 0;
-
- virtual void getScannedStats(HeapStats&) = 0;
-#endif
-
- virtual void prepareHeapForTermination() = 0;
-
- virtual int normalPageCount() = 0;
-
- virtual BaseHeap* split(int normalPages) = 0;
- virtual void merge(BaseHeap* other) = 0;
-
- // Returns a bucket number for inserting a FreeListEntry of a
- // given size. All FreeListEntries in the given bucket, n, have
- // size >= 2^n.
- static int bucketIndexForSize(size_t);
-};
-
-// Thread heaps represent a part of the per-thread Blink heap.
-//
-// Each Blink thread has a number of thread heaps: one general heap
-// that contains any type of object and a number of heaps specialized
-// for specific object types (such as Node).
-//
-// Each thread heap contains the functionality to allocate new objects
-// (potentially adding new pages to the heap), to find and mark
-// objects during conservative stack scanning and to sweep the set of
-// pages after a GC.
-template<typename Header>
-class ThreadHeap : public BaseHeap {
-public:
- ThreadHeap(ThreadState*, int);
- virtual ~ThreadHeap();
- virtual void cleanupPages();
-
- virtual BaseHeapPage* heapPageFromAddress(Address);
-#if ENABLE(GC_PROFILE_MARKING)
- virtual const GCInfo* findGCInfoOfLargeHeapObject(Address);
-#endif
-#if ENABLE(GC_PROFILE_HEAP)
- virtual void snapshot(TracedValue*, ThreadState::SnapshotInfo*);
-#endif
-
- virtual void sweep(HeapStats*);
- virtual void postSweepProcessing();
-
- virtual void clearFreeLists();
- virtual void clearLiveAndMarkDead();
-
- virtual void makeConsistentForSweeping();
-
-#if ENABLE(ASSERT)
- virtual bool isConsistentForSweeping();
-
- virtual void getScannedStats(HeapStats&);
-#endif
-
- ThreadState* threadState() { return m_threadState; }
- HeapStats& stats() { return m_threadState->stats(); }
- void flushHeapContainsCache()
- {
- m_threadState->heapContainsCache()->flush();
- }
-
- inline Address allocate(size_t, const GCInfo*);
- void addToFreeList(Address, size_t);
- inline static size_t roundedAllocationSize(size_t size)
- {
- return allocationSizeFromSize(size) - sizeof(Header);
- }
-
- virtual void prepareHeapForTermination();
-
- virtual int normalPageCount() { return m_numberOfNormalPages; }
-
- virtual BaseHeap* split(int numberOfNormalPages);
- virtual void merge(BaseHeap* splitOffBase);
-
- void removePageFromHeap(HeapPage<Header>*);
-
- PLATFORM_EXPORT void promptlyFreeObject(Header*);
-
-private:
- void addPageToHeap(const GCInfo*);
- PLATFORM_EXPORT Address outOfLineAllocate(size_t, const GCInfo*);
- static size_t allocationSizeFromSize(size_t);
- PLATFORM_EXPORT Address allocateLargeObject(size_t, const GCInfo*);
- Address currentAllocationPoint() const { return m_currentAllocationPoint; }
- size_t remainingAllocationSize() const { return m_remainingAllocationSize; }
- bool ownsNonEmptyAllocationArea() const { return currentAllocationPoint() && remainingAllocationSize(); }
- void setAllocationPoint(Address point, size_t size)
- {
- ASSERT(!point || heapPageFromAddress(point));
- ASSERT(size <= HeapPage<Header>::payloadSize());
- m_currentAllocationPoint = point;
- m_remainingAllocationSize = size;
- }
- void ensureCurrentAllocation(size_t, const GCInfo*);
- bool allocateFromFreeList(size_t);
-
- void freeLargeObject(LargeHeapObject<Header>*, LargeHeapObject<Header>**);
- void allocatePage(const GCInfo*);
-
-#if ENABLE(ASSERT)
- bool pagesToBeSweptContains(Address);
- bool pagesAllocatedDuringSweepingContains(Address);
-#endif
-
- void sweepNormalPages(HeapStats*);
- void sweepLargePages(HeapStats*);
- bool coalesce(size_t);
-
- Address m_currentAllocationPoint;
- size_t m_remainingAllocationSize;
-
- HeapPage<Header>* m_firstPage;
- LargeHeapObject<Header>* m_firstLargeHeapObject;
-
- HeapPage<Header>* m_firstPageAllocatedDuringSweeping;
- HeapPage<Header>* m_lastPageAllocatedDuringSweeping;
-
- // Merge point for parallel sweep.
- HeapPage<Header>* m_mergePoint;
-
- int m_biggestFreeListIndex;
-
- ThreadState* m_threadState;
-
- // All FreeListEntries in the nth list have size >= 2^n.
- FreeListEntry* m_freeLists[blinkPageSizeLog2];
- FreeListEntry* m_lastFreeListEntries[blinkPageSizeLog2];
-
- // Index into the page pools. This is used to ensure that the pages of the
- // same type go into the correct page pool and thus avoid type confusion.
- int m_index;
-
- int m_numberOfNormalPages;
-
- // The promptly freed count contains the number of promptly freed objects
- // since the last sweep or since it was manually reset to delay coalescing.
- size_t m_promptlyFreedCount;
-};
-
-class PLATFORM_EXPORT Heap {
-public:
- static BaseHeapPage* contains(Address);
- static BaseHeapPage* contains(void* pointer) { return contains(reinterpret_cast<Address>(pointer)); }
- static BaseHeapPage* contains(const void* pointer) { return contains(const_cast<void*>(pointer)); }
-#if ENABLE(ASSERT)
- static bool containedInHeapOrOrphanedPage(void*);
-#endif
-
- // Push a trace callback on the marking stack.
- static void pushTraceCallback(CallbackStack**, void* containerObject, TraceCallback);
-
- // Push a trace callback on the post-marking callback stack. These callbacks
- // are called after normal marking (including ephemeron iteration).
- static void pushPostMarkingCallback(void*, TraceCallback);
-
- // Add a weak pointer callback to the weak callback work list. General
- // object pointer callbacks are added to a thread local weak callback work
- // list and the callback is called on the thread that owns the object, with
- // the closure pointer as an argument. Most of the time, the closure and
- // the containerObject can be the same thing, but the containerObject is
- // constrained to be on the heap, since the heap is used to identify the
- // correct thread.
- static void pushWeakObjectPointerCallback(void* closure, void* containerObject, WeakPointerCallback);
-
- // Similar to the more general pushWeakObjectPointerCallback, but cell
- // pointer callbacks are added to a static callback work list and the weak
- // callback is performed on the thread performing garbage collection. This
- // is OK because cells are just cleared and no deallocation can happen.
- static void pushWeakCellPointerCallback(void** cell, WeakPointerCallback);
-
- // Pop the top of the marking stack and call the callback with the visitor
- // and the object. Returns false when there is nothing more to do.
- template<CallbackInvocationMode Mode> static bool popAndInvokeTraceCallback(Visitor*);
-
- // Remove an item from the post-marking callback stack and call
- // the callback with the visitor and the object pointer. Returns
- // false when there is nothing more to do.
- static bool popAndInvokePostMarkingCallback(Visitor*);
-
- // Remove an item from the weak callback work list and call the callback
- // with the visitor and the closure pointer. Returns false when there is
- // nothing more to do.
- static bool popAndInvokeWeakPointerCallback(Visitor*);
-
- // Register an ephemeron table for fixed-point iteration.
- static void registerWeakTable(void* containerObject, EphemeronCallback, EphemeronCallback);
-#if ENABLE(ASSERT)
- static bool weakTableRegistered(const void*);
-#endif
-
- template<typename T, typename HeapTraits = HeapTypeTrait<T> > static Address allocate(size_t);
- template<typename T> static Address reallocate(void* previous, size_t);
-
- static void collectGarbage(ThreadState::StackState);
- static void collectGarbageForTerminatingThread(ThreadState*);
- static void collectAllGarbage();
- static void processMarkingStackEntries(int* numberOfMarkingThreads);
- static void processMarkingStackOnMultipleThreads();
- static void processMarkingStackInParallel();
- template<CallbackInvocationMode Mode> static void processMarkingStack();
- static void postMarkingProcessing();
- static void globalWeakProcessing();
- static void setForcePreciseGCForTesting();
-
- static void prepareForGC();
-
- // Conservatively checks whether an address is a pointer in any of the thread
- // heaps. If so marks the object pointed to as live.
- static Address checkAndMarkPointer(Visitor*, Address);
-
-#if ENABLE(GC_PROFILE_MARKING)
- // Dump the path to specified object on the next GC. This method is to be invoked from GDB.
- static void dumpPathToObjectOnNextGC(void* p);
-
- // Forcibly find GCInfo of the object at Address.
- // This is slow and should only be used for debug purposes.
- // It involves finding the heap page and scanning the heap page for an object header.
- static const GCInfo* findGCInfo(Address);
-
- static String createBacktraceString();
-#endif
-
- // Collect heap stats for all threads attached to the Blink
- // garbage collector. Should only be called during garbage
- // collection where threads are known to be at safe points.
- static void getStats(HeapStats*);
-
- static void getHeapSpaceSize(uint64_t*, uint64_t*);
-
- static void makeConsistentForSweeping();
-
-#if ENABLE(ASSERT)
- static bool isConsistentForSweeping();
-#endif
-
- static void flushHeapDoesNotContainCache();
- static bool heapDoesNotContainCacheIsEmpty() { return s_heapDoesNotContainCache->isEmpty(); }
-
- // Return true if the last GC found a pointer into a heap page
- // during conservative scanning.
- static bool lastGCWasConservative() { return s_lastGCWasConservative; }
-
- static FreePagePool* freePagePool() { return s_freePagePool; }
- static OrphanedPagePool* orphanedPagePool() { return s_orphanedPagePool; }
-
-private:
- static Visitor* s_markingVisitor;
- static Vector<OwnPtr<blink::WebThread> >* s_markingThreads;
- static CallbackStack* s_markingStack;
- static CallbackStack* s_postMarkingCallbackStack;
- static CallbackStack* s_weakCallbackStack;
- static CallbackStack* s_ephemeronStack;
- static HeapDoesNotContainCache* s_heapDoesNotContainCache;
- static bool s_shutdownCalled;
- static bool s_lastGCWasConservative;
- static FreePagePool* s_freePagePool;
- static OrphanedPagePool* s_orphanedPagePool;
- friend class ThreadState;
-};
-
-// The NoAllocationScope class is used in debug mode to catch unwanted
-// allocations. E.g. allocations during GC.
-template<ThreadAffinity Affinity>
-class NoAllocationScope {
-public:
- NoAllocationScope() : m_active(true) { enter(); }
-
- explicit NoAllocationScope(bool active) : m_active(active) { enter(); }
-
- NoAllocationScope(const NoAllocationScope& other) : m_active(other.m_active) { enter(); }
-
- NoAllocationScope& operator=(const NoAllocationScope& other)
- {
- release();
- m_active = other.m_active;
- enter();
- return *this;
- }
-
- ~NoAllocationScope() { release(); }
-
- void release()
- {
- if (m_active) {
- ThreadStateFor<Affinity>::state()->leaveNoAllocationScope();
- m_active = false;
- }
- }
-
-private:
- void enter() const
- {
- if (m_active)
- ThreadStateFor<Affinity>::state()->enterNoAllocationScope();
- }
-
- bool m_active;
-};
-
-// Classes that contain heap references but aren't themselves heap
-// allocated, have some extra macros available which allows their use
-// to be restricted to cases where the garbage collector is able
-// to discover their heap references.
-//
-// STACK_ALLOCATED(): Use if the object is only stack allocated. Heap objects
-// should be in Members but you do not need the trace method as they are on
-// the stack. (Down the line these might turn in to raw pointers, but for
-// now Members indicates that we have thought about them and explicitly
-// taken care of them.)
-//
-// DISALLOW_ALLOCATION(): Cannot be allocated with new operators but can
-// be a part object. If it has Members you need a trace method and the
-// containing object needs to call that trace method.
-//
-// ALLOW_ONLY_INLINE_ALLOCATION(): Allows only placement new operator.
-// This disallows general allocation of this object but allows to put
-// the object as a value object in collections. If these have Members you
-// need to have a trace method. That trace method will be called
-// automatically by the Heap collections.
-//
-#define DISALLOW_ALLOCATION() \
- private: \
- void* operator new(size_t) = delete; \
- void* operator new(size_t, NotNullTag, void*) = delete; \
- void* operator new(size_t, void*) = delete;
-
-#define ALLOW_ONLY_INLINE_ALLOCATION() \
- public: \
- void* operator new(size_t, NotNullTag, void* location) { return location; } \
- void* operator new(size_t, void* location) { return location; } \
- private: \
- void* operator new(size_t) = delete;
-
-#define STATIC_ONLY(Type) \
- private: \
- Type() = delete;
-
-// These macros insert annotations that the Blink GC plugin for clang uses for
-// verification. STACK_ALLOCATED is used to declare that objects of this type
-// are always stack allocated. GC_PLUGIN_IGNORE is used to make the plugin
-// ignore a particular class or field when checking for proper usage. When using
-// GC_PLUGIN_IGNORE a bug-number should be provided as an argument where the
-// bug describes what needs to happen to remove the GC_PLUGIN_IGNORE again.
-#if COMPILER(CLANG)
-#define STACK_ALLOCATED() \
- private: \
- __attribute__((annotate("blink_stack_allocated"))) \
- void* operator new(size_t) = delete; \
- void* operator new(size_t, NotNullTag, void*) = delete; \
- void* operator new(size_t, void*) = delete;
-
-#define GC_PLUGIN_IGNORE(bug) \
- __attribute__((annotate("blink_gc_plugin_ignore")))
-#else
-#define STACK_ALLOCATED() DISALLOW_ALLOCATION()
-#define GC_PLUGIN_IGNORE(bug)
-#endif
-
-NO_SANITIZE_ADDRESS
-void HeapObjectHeader::checkHeader() const
-{
-#if ENABLE(ASSERT)
- BaseHeapPage* page = pageHeaderFromObject(this);
- ASSERT(page->orphaned() || m_magic == magic);
-#endif
-}
-
-Address HeapObjectHeader::payload()
-{
- return reinterpret_cast<Address>(this) + objectHeaderSize;
-}
-
-size_t HeapObjectHeader::payloadSize()
-{
- return size() - objectHeaderSize;
-}
-
-Address HeapObjectHeader::payloadEnd()
-{
- return reinterpret_cast<Address>(this) + size();
-}
-
-NO_SANITIZE_ADDRESS
-void HeapObjectHeader::mark()
-{
- checkHeader();
- // The use of atomic ops guarantees that the reads and writes are
- // atomic and that no memory operation reorderings take place.
- // Multiple threads can still read the old value and all store the
- // new value. However, the new value will be the same for all of
- // the threads and the end result is therefore consistent.
- unsigned size = acquireLoad(&m_size);
- releaseStore(&m_size, size | markBitMask);
-}
-
-Address FinalizedHeapObjectHeader::payload()
-{
- return reinterpret_cast<Address>(this) + finalizedHeaderSize;
-}
-
-size_t FinalizedHeapObjectHeader::payloadSize()
-{
- return size() - finalizedHeaderSize;
-}
-
-template<typename Header>
-size_t ThreadHeap<Header>::allocationSizeFromSize(size_t size)
-{
- // Check the size before computing the actual allocation size. The
- // allocation size calculation can overflow for large sizes and
- // the check therefore has to happen before any calculation on the
- // size.
- RELEASE_ASSERT(size < maxHeapObjectSize);
-
- // Add space for header.
- size_t allocationSize = size + sizeof(Header);
- // Align size with allocation granularity.
- allocationSize = (allocationSize + allocationMask) & ~allocationMask;
- return allocationSize;
-}
-
-template<typename Header>
-Address ThreadHeap<Header>::allocate(size_t size, const GCInfo* gcInfo)
-{
- size_t allocationSize = allocationSizeFromSize(size);
- bool isLargeObject = allocationSize > blinkPageSize / 2;
- if (isLargeObject)
- return allocateLargeObject(allocationSize, gcInfo);
- if (m_remainingAllocationSize < allocationSize)
- return outOfLineAllocate(size, gcInfo);
- Address headerAddress = m_currentAllocationPoint;
- m_currentAllocationPoint += allocationSize;
- m_remainingAllocationSize -= allocationSize;
- Header* header = new (NotNull, headerAddress) Header(allocationSize, gcInfo);
- size_t payloadSize = allocationSize - sizeof(Header);
- stats().increaseObjectSpace(payloadSize);
- Address result = headerAddress + sizeof(*header);
- ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask));
- // Unpoison the memory used for the object (payload).
- ASAN_UNPOISON_MEMORY_REGION(result, payloadSize);
-#if ENABLE(ASSERT) || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER)
- memset(result, 0, payloadSize);
-#endif
- ASSERT(heapPageFromAddress(headerAddress + allocationSize - 1));
- return result;
-}
-
-template<typename T, typename HeapTraits>
-Address Heap::allocate(size_t size)
-{
- ASSERT_NOT_REACHED();
- return 0;
-}
-
-template<typename T>
-Address Heap::reallocate(void* previous, size_t size)
-{
- if (!size) {
- // If the new size is 0 this is equivalent to either
- // free(previous) or malloc(0). In both cases we do
- // nothing and return 0.
- return 0;
- }
- ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state();
- ASSERT(state->isAllocationAllowed());
- const GCInfo* gcInfo = GCInfoTrait<T>::get();
- int heapIndex = HeapTypeTrait<T>::index(gcInfo->hasFinalizer());
- // FIXME: Currently only supports raw allocation on the
- // GeneralHeap. Hence we assume the header is a
- // FinalizedHeapObjectHeader.
- ASSERT(heapIndex == GeneralHeap || heapIndex == GeneralHeapNonFinalized);
- BaseHeap* heap = state->heap(heapIndex);
- Address address = static_cast<typename HeapTypeTrait<T>::HeapType*>(heap)->allocate(size, gcInfo);
- if (!previous) {
- // This is equivalent to malloc(size).
- return address;
- }
- FinalizedHeapObjectHeader* previousHeader = FinalizedHeapObjectHeader::fromPayload(previous);
- ASSERT(!previousHeader->hasFinalizer());
- ASSERT(previousHeader->gcInfo() == gcInfo);
- size_t copySize = previousHeader->payloadSize();
- if (copySize > size)
- copySize = size;
- memcpy(address, previous, copySize);
- return address;
-}
-
-class HeapAllocatorQuantizer {
-public:
- template<typename T>
- static size_t quantizedSize(size_t count)
- {
- RELEASE_ASSERT(count <= kMaxUnquantizedAllocation / sizeof(T));
- return HeapIndexTrait<CollectionBackingHeap>::HeapType::roundedAllocationSize(count * sizeof(T));
- }
- static const size_t kMaxUnquantizedAllocation = maxHeapObjectSize;
-};
-
-// This is a static-only class used as a trait on collections to make them heap allocated.
-// However see also HeapListHashSetAllocator.
-class HeapAllocator {
-public:
- typedef HeapAllocatorQuantizer Quantizer;
- typedef blink::Visitor Visitor;
- static const bool isGarbageCollected = true;
-
- template <typename Return, typename Metadata>
- static Return backingMalloc(size_t size)
- {
- return reinterpret_cast<Return>(Heap::allocate<Metadata, HeapIndexTrait<CollectionBackingHeap> >(size));
- }
- template <typename Return, typename Metadata>
- static Return zeroedBackingMalloc(size_t size)
- {
- return backingMalloc<Return, Metadata>(size);
- }
- template <typename Return, typename Metadata>
- static Return malloc(size_t size)
- {
- return reinterpret_cast<Return>(Heap::allocate<Metadata>(size));
- }
- PLATFORM_EXPORT static void backingFree(void* address);
-
- static void free(void* address) { }
- template<typename T>
- static void* newArray(size_t bytes)
- {
- ASSERT_NOT_REACHED();
- return 0;
- }
-
- static void deleteArray(void* ptr)
- {
- ASSERT_NOT_REACHED();
- }
-
- static bool isAllocationAllowed()
- {
- ASSERT_NOT_REACHED();
- return false;
- }
-
- static void markUsingGCInfo(Visitor* visitor, const void* buffer)
- {
- visitor->mark(buffer, FinalizedHeapObjectHeader::fromPayload(buffer)->traceCallback());
- }
-
- static void markNoTracing(Visitor* visitor, const void* t) { visitor->markNoTracing(t); }
-
- template<typename T, typename Traits>
- static void trace(Visitor* visitor, T& t)
- {
- }
-
- static void registerDelayedMarkNoTracing(Visitor* visitor, const void* object)
- {
- visitor->registerDelayedMarkNoTracing(object);
- }
-
- static void registerWeakMembers(Visitor* visitor, const void* closure, const void* object, WeakPointerCallback callback)
- {
- visitor->registerWeakMembers(closure, object, callback);
- }
-
- static void registerWeakTable(Visitor* visitor, const void* closure, EphemeronCallback iterationCallback, EphemeronCallback iterationDoneCallback)
- {
- visitor->registerWeakTable(closure, iterationCallback, iterationDoneCallback);
- }
-
-#if ENABLE(ASSERT)
- static bool weakTableRegistered(Visitor* visitor, const void* closure)
- {
- return visitor->weakTableRegistered(closure);
- }
-#endif
-
- template<typename T>
- struct ResultType {
- typedef T* Type;
- };
-
- template<typename T>
- struct OtherType {
- typedef T* Type;
- };
-
- template<typename T>
- static T& getOther(T* other)
- {
- return *other;
- }
-
- static void enterNoAllocationScope()
- {
-#if ENABLE(ASSERT)
- ThreadStateFor<AnyThread>::state()->enterNoAllocationScope();
-#endif
- }
-
- static void leaveNoAllocationScope()
- {
-#if ENABLE(ASSERT)
- ThreadStateFor<AnyThread>::state()->leaveNoAllocationScope();
-#endif
- }
-
-private:
- template<typename T, size_t u, typename V> friend class WTF::Vector;
- template<typename T, typename U, typename V, typename W> friend class WTF::HashSet;
- template<typename T, typename U, typename V, typename W, typename X, typename Y> friend class WTF::HashMap;
-};
-
-template<typename Value>
-static void traceListHashSetValue(Visitor* visitor, Value& value)
-{
-}
-
-// The inline capacity is just a dummy template argument to match the off-heap
-// allocator.
-// This inherits from the static-only HeapAllocator trait class, but we do
-// declare pointers to instances. These pointers are always null, and no
-// objects are instantiated.
-template<typename ValueArg, size_t inlineCapacity>
-struct HeapListHashSetAllocator : public HeapAllocator {
- typedef HeapAllocator TableAllocator;
- typedef WTF::ListHashSetNode<ValueArg, HeapListHashSetAllocator> Node;
-
-public:
- class AllocatorProvider {
- public:
- // For the heap allocation we don't need an actual allocator object, so we just
- // return null.
- HeapListHashSetAllocator* get() const { return 0; }
-
- // No allocator object is needed.
- void createAllocatorIfNeeded() { }
-
- // There is no allocator object in the HeapListHashSet (unlike in
- // the regular ListHashSet) so there is nothing to swap.
- void swap(AllocatorProvider& other) { }
- };
-
- void deallocate(void* dummy) { }
-
- // This is not a static method even though it could be, because it
- // needs to match the one that the (off-heap) ListHashSetAllocator
- // has. The 'this' pointer will always be null.
- void* allocateNode()
- {
- COMPILE_ASSERT(!WTF::IsWeak<ValueArg>::value, WeakPointersInAListHashSetWillJustResultInNullEntriesInTheSetThatsNotWhatYouWantConsiderUsingLinkedHashSetInstead);
- return malloc<void*, Node>(sizeof(Node));
- }
-
- static void traceValue(Visitor* visitor, Node* node)
- {
- traceListHashSetValue(visitor, node->m_value);
- }
-};
-
-// CollectionBackingTraceTrait. Do nothing for things in collections that don't
-// need tracing, or call TraceInCollectionTrait for those that do.
-
-// Specialization for things that don't need marking and have no weak pointers. We
-// do nothing, even if WTF::WeakPointersActStrong.
-template<WTF::ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits>
-struct CollectionBackingTraceTrait<false, WTF::NoWeakHandlingInCollections, strongify, T, Traits> {
- static bool trace(Visitor*, T&) { return false; }
-};
-
-// Specialization for things that either need marking or have weak pointers or
-// both.
-template<bool needsTracing, WTF::WeakHandlingFlag weakHandlingFlag, WTF::ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits>
-struct CollectionBackingTraceTrait {
- static bool trace(Visitor* visitor, T&t)
- {
- return false;
- }
-};
-
-template<typename T> struct WeakHandlingHashTraits : WTF::SimpleClassHashTraits<T> {
- // We want to treat the object as a weak object in the sense that it can
- // disappear from hash sets and hash maps.
- static const WTF::WeakHandlingFlag weakHandlingFlag = WTF::WeakHandlingInCollections;
- // Normally whether or not an object needs tracing is inferred
- // automatically from the presence of the trace method, but we don't
- // necessarily have a trace method, and we may not need one because T
- // can perhaps only be allocated inside collections, never as indpendent
- // objects. Explicitly mark this as needing tracing and it will be traced
- // in collections using the traceInCollection method, which it must have.
- template<typename U = void> struct NeedsTracingLazily {
- static const bool value = true;
- };
- // The traceInCollection method traces differently depending on whether we
- // are strongifying the trace operation. We strongify the trace operation
- // when there are active iterators on the object. In this case all
- // WeakMembers are marked like strong members so that elements do not
- // suddenly disappear during iteration. Returns true if weak pointers to
- // dead objects were found: In this case any strong pointers were not yet
- // traced and the entry should be removed from the collection.
- static bool traceInCollection(Visitor* visitor, T& t, WTF::ShouldWeakPointersBeMarkedStrongly strongify)
- {
- return t.traceInCollection(visitor, strongify);
- }
-};
-
-template<typename T, typename Traits>
-struct TraceTrait<HeapVectorBacking<T, Traits> > {
- typedef HeapVectorBacking<T, Traits> Backing;
- static void trace(Visitor* visitor, void* self)
- {
- }
- static void mark(Visitor* visitor, const Backing* backing)
- {
- }
-};
-
-template<typename T>
-struct IfWeakMember;
-
-template<typename T>
-struct IfWeakMember {
- template<typename U>
- static bool isDead(Visitor*, const U&) { return false; }
-};
-
-template<typename T>
-struct IfWeakMember<WeakMember<T> > {
- static bool isDead(Visitor* visitor, const WeakMember<T>& t) { return !visitor->isAlive(t.get()); }
-};
-
-}
-
-#endif // Heap_h
« sky/engine/core/css/MediaQueryMatcher.h ('K') | « sky/engine/platform/heap/Handle.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698