15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
23c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * Copyright (C) 2013 Google Inc. All rights reserved.
302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met:
702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission.
1702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
31a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#ifndef Heap_h
32a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#define Heap_h
33a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
34a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include "platform/PlatformExport.h"
35a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include "platform/heap/AddressSanitizer.h"
36a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include "platform/heap/ThreadState.h"
37a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include "platform/heap/Visitor.h"
387242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "public/platform/WebThread.h"
39a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "wtf/Assertions.h"
40f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "wtf/HashCountedSet.h"
416f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch#include "wtf/LinkedHashSet.h"
42323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)#include "wtf/ListHashSet.h"
4309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "wtf/OwnPtr.h"
4409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "wtf/PassRefPtr.h"
45323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)#include "wtf/ThreadSafeRefCounted.h"
46a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
47a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include <stdint.h>
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
49c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const size_t blinkPageSizeLog2 = 17;
5209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const size_t blinkPageSize = 1 << blinkPageSizeLog2;
5309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const size_t blinkPageOffsetMask = blinkPageSize - 1;
5409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const size_t blinkPageBaseMask = ~blinkPageOffsetMask;
55197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
56197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// We allocate pages at random addresses but in groups of
57197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// blinkPagesPerRegion at a given random address. We group pages to
58197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// not spread out too much over the address space which would blow
59197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// away the page tables and lead to bad performance.
60197021e6b966cfb06891637935ef33fff06433d1Ben Murdochconst size_t blinkPagesPerRegion = 10;
61197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
6209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Double precision floats are more efficient when 8 byte aligned, so we 8 byte
6309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// align all allocations even on 32 bit.
6409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const size_t allocationGranularity = 8;
6509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const size_t allocationMask = allocationGranularity - 1;
6609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const size_t objectStartBitMapSize = (blinkPageSize + ((8 * allocationGranularity) - 1)) / (8 * allocationGranularity);
6709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const size_t reservedForObjectBitMap = ((objectStartBitMapSize + allocationMask) & ~allocationMask);
68e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)const size_t maxHeapObjectSizeLog2 = 27;
69e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)const size_t maxHeapObjectSize = 1 << maxHeapObjectSizeLog2;
7009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
7109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const size_t markBitMask = 1;
7209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const size_t freeListMask = 2;
73197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// The dead bit is used for objects that have gone through a GC marking, but did
74197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// not get swept before a new GC started. In that case we set the dead bit on
75197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// objects that were not marked in the previous GC to ensure we are not tracing
76197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// them via a conservatively found pointer. Tracing dead objects could lead to
77197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// tracing of already finalized objects in another thread's heap which is a
78197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// use-after-free situation.
79197021e6b966cfb06891637935ef33fff06433d1Ben Murdochconst size_t deadBitMask = 4;
807242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// On free-list entries we reuse the dead bit to distinguish a normal free-list
817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// entry from one that has been promptly freed.
827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciconst size_t promptlyFreedMask = freeListMask | deadBitMask;
83e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILE_HEAP)
84e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)const size_t heapObjectGenerations = 8;
85e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)const size_t maxHeapObjectAge = heapObjectGenerations - 1;
86e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)const size_t heapObjectAgeMask = ~(maxHeapObjectSize - 1);
87e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)const size_t sizeMask = ~heapObjectAgeMask & ~static_cast<size_t>(7);
88e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#else
89197021e6b966cfb06891637935ef33fff06433d1Ben Murdochconst size_t sizeMask = ~static_cast<size_t>(7);
90e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#endif
9109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const uint8_t freelistZapValue = 42;
9209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const uint8_t finalizedZapValue = 24;
93197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// The orphaned zap value must be zero in the lowest bits to allow for using
94197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// the mark bit when tracing.
95197021e6b966cfb06891637935ef33fff06433d1Ben Murdochconst uint8_t orphanedZapValue = 240;
96197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
977242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciconst int numberOfMarkingThreads = 2;
987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciconst int numberOfPagesToConsiderForCoalescing = 100;
1007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
101197021e6b966cfb06891637935ef33fff06433d1Ben Murdochenum CallbackInvocationMode {
102197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    GlobalMarking,
103197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ThreadLocalMarking,
104197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch};
10509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1067242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass CallbackStack;
10709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class HeapStats;
10809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class PageMemory;
10909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<ThreadAffinity affinity> class ThreadLocalPersistents;
11009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T, typename RootsAccessor = ThreadLocalPersistents<ThreadingTrait<T>::Affinity > > class Persistent;
111323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)template<typename T> class CrossThreadPersistent;
11209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
113e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILE_HEAP)
114e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)class TracedValue;
115e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#endif
116e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
117a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben MurdochPLATFORM_EXPORT size_t osPageSize();
11809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
11909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Blink heap pages are set up with a guard page before and after the
12009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// payload.
12109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)inline size_t blinkPagePayloadSize()
12209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
12309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return blinkPageSize - 2 * osPageSize();
12409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
12509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
12609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Blink heap pages are aligned to the Blink heap page size.
12709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Therefore, the start of a Blink page can be obtained by
12809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// rounding down to the Blink page size.
12909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)inline Address roundToBlinkPageStart(Address address)
13009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
13109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address) & blinkPageBaseMask);
13209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
13309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
134f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)inline Address roundToBlinkPageEnd(Address address)
135f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles){
136f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    return reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address - 1) & blinkPageBaseMask) + blinkPageSize;
137f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)}
138f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)
13909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Compute the amount of padding we have to add to a header to make
14009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// the size of the header plus the padding a multiple of 8 bytes.
14109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename Header>
14209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)inline size_t headerPadding()
14309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
14409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return (allocationGranularity - (sizeof(Header) % allocationGranularity)) % allocationGranularity;
14509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
14609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
14709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Masks an address down to the enclosing blink page base address.
14809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)inline Address blinkPageAddress(Address address)
14909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
15009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address) & blinkPageBaseMask);
15109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
15209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
153197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT)
15409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
15509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Sanity check for a page header address: the address of the page
15609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// header should be OS page size away from being Blink page size
15709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// aligned.
15809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)inline bool isPageHeaderAddress(Address address)
15909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
16009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return !((reinterpret_cast<uintptr_t>(address) & blinkPageOffsetMask) - osPageSize());
16109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
16209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif
16309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
164197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// Mask an address down to the enclosing oilpan heap base page.
16509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// All oilpan heap pages are aligned at blinkPageBase plus an OS page size.
166a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// FIXME: Remove PLATFORM_EXPORT once we get a proper public interface to our typed heaps.
16709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// This is only exported to enable tests in HeapTest.cpp.
168197021e6b966cfb06891637935ef33fff06433d1Ben MurdochPLATFORM_EXPORT inline BaseHeapPage* pageHeaderFromObject(const void* object)
16909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
170197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    Address address = reinterpret_cast<Address>(const_cast<void*>(object));
171197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return reinterpret_cast<BaseHeapPage*>(blinkPageAddress(address) + osPageSize());
17209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
17309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
17409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Large allocations are allocated as separate objects and linked in a
17509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// list.
17609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)//
17709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// In order to use the same memory allocation routines for everything
17809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// allocated in the heap, large objects are considered heap pages
17909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// containing only one object.
18009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)//
18109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// The layout of a large heap object is as follows:
18209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)//
18309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// | BaseHeapPage | next pointer | FinalizedHeapObjectHeader or HeapObjectHeader | payload |
18409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename Header>
18509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class LargeHeapObject : public BaseHeapPage {
18609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)public:
187d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    LargeHeapObject(PageMemory* storage, const GCInfo* gcInfo, ThreadState* state) : BaseHeapPage(storage, gcInfo, state)
18809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
18909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        COMPILE_ASSERT(!(sizeof(LargeHeapObject<Header>) & allocationMask), large_heap_object_header_misaligned);
19009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
19109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
192f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    virtual void checkAndMarkPointer(Visitor*, Address) OVERRIDE;
193f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    virtual bool isLargeObject() OVERRIDE { return true; }
19409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
195e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILE_MARKING)
196f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    virtual const GCInfo* findGCInfo(Address address)
197f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    {
198f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)        if (!objectContains(address))
199f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)            return 0;
200f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        return gcInfo();
201f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    }
202f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#endif
203f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
204e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILE_HEAP)
205e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    void snapshot(TracedValue*, ThreadState::SnapshotInfo*);
206e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#endif
207e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
20809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void link(LargeHeapObject<Header>** previousNext)
20909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
21009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        m_next = *previousNext;
21109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        *previousNext = this;
21209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
21309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
21409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void unlink(LargeHeapObject<Header>** previousNext)
21509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
21609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        *previousNext = m_next;
21709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
21809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
219f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    // The LargeHeapObject pseudo-page contains one actual object. Determine
220f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    // whether the pointer is within that object.
221f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    bool objectContains(Address object)
222f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    {
223f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)        return (payload() <= object) && (object < address() + size());
224f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    }
225f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)
226f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    // Returns true for any address that is on one of the pages that this
227f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    // large object uses. That ensures that we can use a negative result to
228f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    // populate the negative page cache.
229197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    virtual bool contains(Address object) OVERRIDE
23009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
231f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)        return roundToBlinkPageStart(address()) <= object && object < roundToBlinkPageEnd(address() + size());
23209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
23309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
23409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    LargeHeapObject<Header>* next()
23509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
23609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return m_next;
23709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
23809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
23909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    size_t size()
24009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
24109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return heapObjectHeader()->size() + sizeof(LargeHeapObject<Header>) + headerPadding<Header>();
24209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
24309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
24409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    Address payload() { return heapObjectHeader()->payload(); }
24509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    size_t payloadSize() { return heapObjectHeader()->payloadSize(); }
24609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
24709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    Header* heapObjectHeader()
24809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
24909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        Address headerAddress = address() + sizeof(LargeHeapObject<Header>) + headerPadding<Header>();
25009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return reinterpret_cast<Header*>(headerAddress);
25109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
25209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
25309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    bool isMarked();
25409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void unmark();
25509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void getStats(HeapStats&);
25609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void mark(Visitor*);
25709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void finalize();
258197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    void setDeadMark();
259197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    virtual void markOrphaned()
260197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    {
261197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // Zap the payload with a recognizable value to detect any incorrect
262197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // cross thread pointer usage.
263197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        memset(payload(), orphanedZapValue, payloadSize());
264197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        BaseHeapPage::markOrphaned();
265197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
26609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
26709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)private:
26809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    friend class ThreadHeap<Header>;
26909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
27009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    LargeHeapObject<Header>* m_next;
27109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
27209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
27309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// The BasicObjectHeader is the minimal object header. It is used when
27409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// encountering heap space of size allocationGranularity to mark it as
27509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// as freelist entry.
276a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochclass PLATFORM_EXPORT BasicObjectHeader {
27709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)public:
27809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    NO_SANITIZE_ADDRESS
27909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    explicit BasicObjectHeader(size_t encodedSize)
28009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        : m_size(encodedSize) { }
28109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
28209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static size_t freeListEncodedSize(size_t size) { return size | freeListMask; }
28309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
28409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    NO_SANITIZE_ADDRESS
28509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    bool isFree() { return m_size & freeListMask; }
28609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
28709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    NO_SANITIZE_ADDRESS
2887242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    bool isPromptlyFreed() { return (m_size & promptlyFreedMask) == promptlyFreedMask; }
2897242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2907242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    NO_SANITIZE_ADDRESS
2917242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    void markPromptlyFreed() { m_size |= promptlyFreedMask; }
2927242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2937242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    NO_SANITIZE_ADDRESS
29409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    size_t size() const { return m_size & sizeMask; }
29509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
296e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILE_HEAP)
297e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    NO_SANITIZE_ADDRESS
298e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    size_t encodedSize() const { return m_size; }
299e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
300e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    NO_SANITIZE_ADDRESS
301e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    size_t age() const { return m_size >> maxHeapObjectSizeLog2; }
302e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
303e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    NO_SANITIZE_ADDRESS
304e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    void incAge()
305e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    {
306e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        size_t current = age();
307e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        if (current < maxHeapObjectAge)
308e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)            m_size = ((current + 1) << maxHeapObjectSizeLog2) | (m_size & ~heapObjectAgeMask);
309e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    }
310e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#endif
311e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
31209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)protected:
3137242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    volatile unsigned m_size;
31409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
31509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
31609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Our heap object layout is layered with the HeapObjectHeader closest
31709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// to the payload, this can be wrapped in a FinalizedObjectHeader if the
31809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// object is on the GeneralHeap and not on a specific TypedHeap.
31909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Finally if the object is a large object (> blinkPageSize/2) then it is
32009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// wrapped with a LargeObjectHeader.
32109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)//
32209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Object memory layout:
32309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// [ LargeObjectHeader | ] [ FinalizedObjectHeader | ] HeapObjectHeader | payload
32409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// The [ ] notation denotes that the LargeObjectHeader and the FinalizedObjectHeader
32509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// are independently optional.
326a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochclass PLATFORM_EXPORT HeapObjectHeader : public BasicObjectHeader {
32709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)public:
32809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    NO_SANITIZE_ADDRESS
32909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    explicit HeapObjectHeader(size_t encodedSize)
33009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        : BasicObjectHeader(encodedSize)
331197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT)
33209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        , m_magic(magic)
33309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif
33409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    { }
33509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
33609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    NO_SANITIZE_ADDRESS
33709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    HeapObjectHeader(size_t encodedSize, const GCInfo*)
33809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        : BasicObjectHeader(encodedSize)
339197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT)
34009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        , m_magic(magic)
34109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif
34209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    { }
34309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
34409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    inline void checkHeader() const;
34509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    inline bool isMarked() const;
34609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
34709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    inline void mark();
34809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    inline void unmark();
34909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
350f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    inline const GCInfo* gcInfo() { return 0; }
351f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
35209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    inline Address payload();
35309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    inline size_t payloadSize();
35409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    inline Address payloadEnd();
35509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
356197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    inline void setDeadMark();
357197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    inline void clearDeadMark();
358197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    inline bool hasDeadMark() const;
35909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
36009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Zap magic number with a new magic number that means there was once an
36109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // object allocated here, but it was freed because nobody marked it during
36209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // GC.
36309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void zapMagic();
36409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
36509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static void finalize(const GCInfo*, Address, size_t);
366d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    static HeapObjectHeader* fromPayload(const void*);
36709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
36809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static const intptr_t magic = 0xc0de247;
36909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static const intptr_t zappedMagic = 0xC0DEdead;
37009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // The zap value for vtables should be < 4K to ensure it cannot be
37109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // used for dispatch.
37209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static const intptr_t zappedVTable = 0xd0d;
37309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
37409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)private:
375197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT)
37609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    intptr_t m_magic;
37709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif
37809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
37909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
38009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const size_t objectHeaderSize = sizeof(HeapObjectHeader);
38109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
38209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Each object on the GeneralHeap needs to carry a pointer to its
38309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// own GCInfo structure for tracing and potential finalization.
384a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochclass PLATFORM_EXPORT FinalizedHeapObjectHeader : public HeapObjectHeader {
38509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)public:
38609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    NO_SANITIZE_ADDRESS
38709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    FinalizedHeapObjectHeader(size_t encodedSize, const GCInfo* gcInfo)
38809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        : HeapObjectHeader(encodedSize)
38909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        , m_gcInfo(gcInfo)
39009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
39109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
39209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
39309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    inline Address payload();
39409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    inline size_t payloadSize();
39509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
39609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    NO_SANITIZE_ADDRESS
39709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    const GCInfo* gcInfo() { return m_gcInfo; }
39809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
39909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    NO_SANITIZE_ADDRESS
40009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    TraceCallback traceCallback() { return m_gcInfo->m_trace; }
40109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
40209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void finalize();
40309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
40409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    NO_SANITIZE_ADDRESS
40509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    inline bool hasFinalizer() { return m_gcInfo->hasFinalizer(); }
40609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
407d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    static FinalizedHeapObjectHeader* fromPayload(const void*);
40809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
409a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    NO_SANITIZE_ADDRESS
410a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    bool hasVTable() { return m_gcInfo->hasVTable(); }
411a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
41209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)private:
41309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    const GCInfo* m_gcInfo;
41409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
41509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
41609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const size_t finalizedHeaderSize = sizeof(FinalizedHeapObjectHeader);
41709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
41809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class FreeListEntry : public HeapObjectHeader {
41909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)public:
42009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    NO_SANITIZE_ADDRESS
42109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    explicit FreeListEntry(size_t size)
42209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        : HeapObjectHeader(freeListEncodedSize(size))
42309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        , m_next(0)
42409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
425197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT) && !defined(ADDRESS_SANITIZER)
42609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // Zap free area with asterisks, aka 0x2a2a2a2a.
427197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // For ASan don't zap since we keep accounting in the freelist entry.
42809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        for (size_t i = sizeof(*this); i < size; i++)
42909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            reinterpret_cast<Address>(this)[i] = freelistZapValue;
43009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        ASSERT(size >= objectHeaderSize);
43109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        zapMagic();
43209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif
43309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
43409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
43509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    Address address() { return reinterpret_cast<Address>(this); }
43609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
43709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    NO_SANITIZE_ADDRESS
43809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void unlink(FreeListEntry** prevNext)
43909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
44009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        *prevNext = m_next;
44109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        m_next = 0;
44209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
44309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
44409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    NO_SANITIZE_ADDRESS
44509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void link(FreeListEntry** prevNext)
44609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
44709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        m_next = *prevNext;
44809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        *prevNext = this;
44909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
45009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
4519e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    NO_SANITIZE_ADDRESS
4529e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    FreeListEntry* next() const { return m_next; }
4539e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
4549e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    NO_SANITIZE_ADDRESS
4559e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    void append(FreeListEntry* next)
4569e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    {
4579e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        ASSERT(!m_next);
4589e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        m_next = next;
4599e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    }
4609e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
46109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#if defined(ADDRESS_SANITIZER)
46209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    NO_SANITIZE_ADDRESS
46309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    bool shouldAddToFreeList()
46409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
46509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // Init if not already magic.
46609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if ((m_asanMagic & ~asanDeferMemoryReuseMask) != asanMagic) {
46709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            m_asanMagic = asanMagic | asanDeferMemoryReuseCount;
46809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return false;
46909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
47009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // Decrement if count part of asanMagic > 0.
47109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (m_asanMagic & asanDeferMemoryReuseMask)
47209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            m_asanMagic--;
47309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return !(m_asanMagic & asanDeferMemoryReuseMask);
47409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
47509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif
47609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
47709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)private:
47809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    FreeListEntry* m_next;
47909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#if defined(ADDRESS_SANITIZER)
48009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    unsigned m_asanMagic;
48109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif
48209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
48309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
48409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Representation of Blink heap pages.
48509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)//
48609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Pages are specialized on the type of header on the object they
48709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// contain. If a heap page only contains a certain type of object all
48809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// of the objects will have the same GCInfo pointer and therefore that
48909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// pointer can be stored in the HeapPage instead of in the header of
49009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// each object. In that case objects have only a HeapObjectHeader and
49109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// not a FinalizedHeapObjectHeader saving a word per object.
49209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename Header>
49309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class HeapPage : public BaseHeapPage {
49409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)public:
49509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    HeapPage(PageMemory*, ThreadHeap<Header>*, const GCInfo*);
49609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
49709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void link(HeapPage**);
4989e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    static void unlink(ThreadHeap<Header>*, HeapPage*, HeapPage**);
49909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
50009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    bool isEmpty();
50109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
502f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    // Returns true for the whole blinkPageSize page that the page is on, even
503f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    // for the header, and the unmapped guard page at the start. That ensures
504f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    // the result can be used to populate the negative page cache.
505197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    virtual bool contains(Address addr) OVERRIDE
50609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
50709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        Address blinkPageStart = roundToBlinkPageStart(address());
508f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        ASSERT(blinkPageStart == address() - osPageSize()); // Page is at aligned address plus guard page size.
509f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)        return blinkPageStart <= addr && addr < blinkPageStart + blinkPageSize;
51009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
51109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
51209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    HeapPage* next() { return m_next; }
51309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
51409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    Address payload()
51509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
51609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return address() + sizeof(*this) + headerPadding<Header>();
51709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
51809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
51909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static size_t payloadSize()
52009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
52109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return (blinkPagePayloadSize() - sizeof(HeapPage) - headerPadding<Header>()) & ~allocationMask;
52209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
52309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
52409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    Address end() { return payload() + payloadSize(); }
52509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
52609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void getStats(HeapStats&);
527197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    void clearLiveAndMarkDead();
5289e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    void sweep(HeapStats*, ThreadHeap<Header>*);
52909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void clearObjectStartBitMap();
53009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void finalize(Header*);
531f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    virtual void checkAndMarkPointer(Visitor*, Address) OVERRIDE;
532e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILE_MARKING)
533f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    const GCInfo* findGCInfo(Address) OVERRIDE;
534f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#endif
535e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILE_HEAP)
536e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    virtual void snapshot(TracedValue*, ThreadState::SnapshotInfo*);
537e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#endif
5389e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
53909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#if defined(ADDRESS_SANITIZER)
54009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void poisonUnmarkedObjects();
54109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif
542197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    NO_SANITIZE_ADDRESS
543197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    virtual void markOrphaned()
544197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    {
545197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // Zap the payload with a recognizable value to detect any incorrect
546197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // cross thread pointer usage.
547197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if defined(ADDRESS_SANITIZER)
548197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // Don't use memset when running with ASan since this needs to zap
549197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // poisoned memory as well and the NO_SANITIZE_ADDRESS annotation
550197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // only works for code in this method and not for calls to memset.
551197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        for (Address current = payload(); current < payload() + payloadSize(); ++current)
552197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            *current = orphanedZapValue;
553197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#else
554197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        memset(payload(), orphanedZapValue, payloadSize());
555197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#endif
556197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        BaseHeapPage::markOrphaned();
557197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
55809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
55909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)protected:
560f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    Header* findHeaderFromAddress(Address);
56109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void populateObjectStartBitMap();
56209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    bool isObjectStartBitMapComputed() { return m_objectStartBitMapComputed; }
56309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    TraceCallback traceCallback(Header*);
564a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    bool hasVTable(Header*);
56509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
5669e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    intptr_t padding() const { return m_padding; }
5679e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
56809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    HeapPage<Header>* m_next;
5699e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    intptr_t m_padding; // Preserve 8-byte alignment on 32-bit systems.
57009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    bool m_objectStartBitMapComputed;
57109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    uint8_t m_objectStartBitMap[reservedForObjectBitMap];
57209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
57309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    friend class ThreadHeap<Header>;
57409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
57509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
576f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)class AddressEntry {
577f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)public:
578f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    AddressEntry() : m_address(0) { }
579f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)
580f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    explicit AddressEntry(Address address) : m_address(address) { }
581f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)
582f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    Address address() const { return m_address; }
583f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)
584f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)private:
585f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    Address m_address;
586f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)};
587f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)
588f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)class PositiveEntry : public AddressEntry {
589f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)public:
590f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    PositiveEntry()
591f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)        : AddressEntry()
592f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)        , m_containingPage(0)
593f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    {
594f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    }
595f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)
596f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    PositiveEntry(Address address, BaseHeapPage* containingPage)
597f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)        : AddressEntry(address)
598f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)        , m_containingPage(containingPage)
599f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    {
600f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    }
601f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)
602f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    BaseHeapPage* result() const { return m_containingPage; }
603f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)
604f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    typedef BaseHeapPage* LookupResult;
605f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)
606f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)private:
607f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    BaseHeapPage* m_containingPage;
608f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)};
609f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)
610f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)class NegativeEntry : public AddressEntry {
611f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)public:
612f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    NegativeEntry() : AddressEntry() { }
613f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)
614f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    NegativeEntry(Address address, bool) : AddressEntry(address) { }
615f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)
616f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    bool result() const { return true; }
617f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)
618f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    typedef bool LookupResult;
619f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)};
620f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)
621f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)// A HeapExtentCache provides a fast way of taking an arbitrary
62209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// pointer-sized word, and determining whether it can be interpreted
62309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// as a pointer to an area that is managed by the garbage collected
62409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Blink heap. There is a cache of 'pages' that have previously been
625f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)// determined to be wholly inside the heap. The size of these pages must be
626f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)// smaller than the allocation alignment of the heap pages. We determine
627f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)// on-heap-ness by rounding down the pointer to the nearest page and looking up
628f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)// the page in the cache. If there is a miss in the cache we can ask the heap
629f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)// to determine the status of the pointer by iterating over all of the heap.
630f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)// The result is then cached in the two-way associative page cache.
63109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)//
632f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)// A HeapContainsCache is a positive cache. Therefore, it must be flushed when
633f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)// memory is removed from the Blink heap. The HeapDoesNotContainCache is a
634f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)// negative cache, so it must be flushed when memory is added to the heap.
635f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)template<typename Entry>
636f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)class HeapExtentCache {
63709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)public:
638f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    HeapExtentCache()
639f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)        : m_entries(adoptArrayPtr(new Entry[HeapExtentCache::numberOfEntries]))
640f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)        , m_hasEntries(false)
641f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    {
642f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    }
64309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
64409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void flush();
64509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    bool contains(Address);
646f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    bool isEmpty() { return !m_hasEntries; }
64709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
64809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Perform a lookup in the cache.
64909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    //
650f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    // If lookup returns null/false the argument address was not found in
65109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // the cache and it is unknown if the address is in the Blink
65209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // heap.
65309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    //
654f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    // If lookup returns true/a page, the argument address was found in the
655f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    // cache. For the HeapContainsCache this means the address is in the heap.
656f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    // For the HeapDoesNotContainCache this means the address is not in the
657f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    // heap.
658f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    PLATFORM_EXPORT typename Entry::LookupResult lookup(Address);
65909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
660f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    // Add an entry to the cache.
661f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    PLATFORM_EXPORT void addEntry(Address, typename Entry::LookupResult);
66209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
663f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)private:
66409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static const int numberOfEntriesLog2 = 12;
66509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static const int numberOfEntries = 1 << numberOfEntriesLog2;
66609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
66709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static size_t hash(Address);
66809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
669f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    WTF::OwnPtr<Entry[]> m_entries;
670f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    bool m_hasEntries;
67109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
67209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    friend class ThreadState;
67309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
67409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
675f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)// Normally these would be typedefs instead of subclasses, but that makes them
676f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)// very hard to forward declare.
677f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)class HeapContainsCache : public HeapExtentCache<PositiveEntry> {
678f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)public:
679f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    BaseHeapPage* lookup(Address);
680f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    void addEntry(Address, BaseHeapPage*);
681f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)};
682f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)
683f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)class HeapDoesNotContainCache : public HeapExtentCache<NegativeEntry> { };
684f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)
685323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)// FIXME: This is currently used by the WebAudio code.
686323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)// We should attempt to restructure the WebAudio code so that the main thread
687323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)// alone determines life-time and receives messages about life-time from the
688323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)// audio thread.
689323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)template<typename T>
690323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)class ThreadSafeRefCountedGarbageCollected : public GarbageCollectedFinalized<T>, public WTF::ThreadSafeRefCountedBase {
691323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    WTF_MAKE_NONCOPYABLE(ThreadSafeRefCountedGarbageCollected);
692323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
693323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)public:
694323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    ThreadSafeRefCountedGarbageCollected()
695323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    {
6969e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        makeKeepAlive();
697323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    }
698323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
699323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // Override ref to deal with a case where a reference count goes up
700323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // from 0 to 1. This can happen in the following scenario:
701323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // (1) The reference count becomes 0, but on-stack pointers keep references to the object.
702323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // (2) The on-stack pointer is assigned to a RefPtr. The reference count becomes 1.
703323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // In this case, we have to resurrect m_keepAlive.
704323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    void ref()
705323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    {
706323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        MutexLocker lock(m_mutex);
707323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        if (UNLIKELY(!refCount())) {
7089e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)            makeKeepAlive();
709323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        }
710323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        WTF::ThreadSafeRefCountedBase::ref();
711323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    }
712323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
713323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // Override deref to deal with our own deallocation based on ref counting.
714323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    void deref()
715323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    {
716323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        MutexLocker lock(m_mutex);
717323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        if (derefBase()) {
718323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            ASSERT(m_keepAlive);
719323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            m_keepAlive.clear();
720323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        }
721323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    }
722323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
723323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    using GarbageCollectedFinalized<T>::operator new;
724323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    using GarbageCollectedFinalized<T>::operator delete;
725323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
726323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)protected:
727323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    ~ThreadSafeRefCountedGarbageCollected() { }
728323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
729323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)private:
7309e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    void makeKeepAlive()
7319e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    {
7329e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        ASSERT(!m_keepAlive);
7339e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        m_keepAlive = adoptPtr(new CrossThreadPersistent<T>(static_cast<T*>(this)));
7349e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    }
7359e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
736323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    OwnPtr<CrossThreadPersistent<T> > m_keepAlive;
737323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    mutable Mutex m_mutex;
738323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)};
739323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
740197021e6b966cfb06891637935ef33fff06433d1Ben Murdochtemplate<typename DataType>
741197021e6b966cfb06891637935ef33fff06433d1Ben Murdochclass PagePool {
742197021e6b966cfb06891637935ef33fff06433d1Ben Murdochprotected:
743197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    PagePool();
744197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
745197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    class PoolEntry {
746197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    public:
747197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        PoolEntry(DataType* data, PoolEntry* next)
748197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            : data(data)
749197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            , next(next)
750197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        { }
751197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
752197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        DataType* data;
753197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        PoolEntry* next;
754197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    };
755197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
756197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    PoolEntry* m_pool[NumberOfHeaps];
757197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch};
758197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
759197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// Once pages have been used for one type of thread heap they will never be
760197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// reused for another type of thread heap. Instead of unmapping, we add the
761197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// pages to a pool of pages to be reused later by a thread heap of the same
762197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// type. This is done as a security feature to avoid type confusion. The
763197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// heaps are type segregated by having separate thread heaps for different
764197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// types of objects. Holding on to pages ensures that the same virtual address
765197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// space cannot be used for objects of another type than the type contained
766197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// in this page to begin with.
767197021e6b966cfb06891637935ef33fff06433d1Ben Murdochclass FreePagePool : public PagePool<PageMemory> {
768197021e6b966cfb06891637935ef33fff06433d1Ben Murdochpublic:
769197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ~FreePagePool();
770197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    void addFreePage(int, PageMemory*);
771197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    PageMemory* takeFreePage(int);
772197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
773197021e6b966cfb06891637935ef33fff06433d1Ben Murdochprivate:
774197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    Mutex m_mutex[NumberOfHeaps];
775197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch};
776197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
777197021e6b966cfb06891637935ef33fff06433d1Ben Murdochclass OrphanedPagePool : public PagePool<BaseHeapPage> {
778197021e6b966cfb06891637935ef33fff06433d1Ben Murdochpublic:
779197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ~OrphanedPagePool();
780197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    void addOrphanedPage(int, BaseHeapPage*);
781197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    void decommitOrphanedPages();
782197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT)
783197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    bool contains(void*);
784197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#endif
785197021e6b966cfb06891637935ef33fff06433d1Ben Murdochprivate:
786197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    void clearMemory(PageMemory*);
787197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch};
788197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
78909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Non-template super class used to pass a heap around to other classes.
79009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class BaseHeap {
79109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)public:
79209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual ~BaseHeap() { }
793197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    virtual void cleanupPages() = 0;
79409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
79509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Find the page in this thread heap containing the given
79609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // address. Returns 0 if the address is not contained in any
79709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // page in this thread heap.
79809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual BaseHeapPage* heapPageFromAddress(Address) = 0;
79909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
800e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILE_MARKING)
801f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    virtual const GCInfo* findGCInfoOfLargeHeapObject(Address) = 0;
802f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#endif
803f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
804e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILE_HEAP)
805e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    virtual void snapshot(TracedValue*, ThreadState::SnapshotInfo*) = 0;
806e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#endif
807e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
80809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Sweep this part of the Blink heap. This finalizes dead objects
80909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // and builds freelists for all the unused memory.
8109e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    virtual void sweep(HeapStats*) = 0;
8119e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    virtual void postSweepProcessing() = 0;
81209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
81309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual void clearFreeLists() = 0;
814197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    virtual void clearLiveAndMarkDead() = 0;
8159e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
8169e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    virtual void makeConsistentForSweeping() = 0;
8179e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
818197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT)
8199e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    virtual bool isConsistentForSweeping() = 0;
8209e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
82109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual void getScannedStats(HeapStats&) = 0;
82209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif
82309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
824197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    virtual void prepareHeapForTermination() = 0;
825197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
8269e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    virtual int normalPageCount() = 0;
8279e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
8289e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    virtual BaseHeap* split(int normalPages) = 0;
8299e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    virtual void merge(BaseHeap* other) = 0;
8309e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
83109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Returns a bucket number for inserting a FreeListEntry of a
83209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // given size. All FreeListEntries in the given bucket, n, have
83309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // size >= 2^n.
83409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static int bucketIndexForSize(size_t);
83509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
83609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
83709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Thread heaps represent a part of the per-thread Blink heap.
83809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)//
83909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Each Blink thread has a number of thread heaps: one general heap
84009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// that contains any type of object and a number of heaps specialized
84109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// for specific object types (such as Node).
84209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)//
84309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Each thread heap contains the functionality to allocate new objects
84409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// (potentially adding new pages to the heap), to find and mark
84509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// objects during conservative stack scanning and to sweep the set of
84609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// pages after a GC.
84709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename Header>
84809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class ThreadHeap : public BaseHeap {
84909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)public:
850197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ThreadHeap(ThreadState*, int);
85109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual ~ThreadHeap();
852197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    virtual void cleanupPages();
85309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
85409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual BaseHeapPage* heapPageFromAddress(Address);
855e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILE_MARKING)
856f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    virtual const GCInfo* findGCInfoOfLargeHeapObject(Address);
857f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#endif
858e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILE_HEAP)
859e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    virtual void snapshot(TracedValue*, ThreadState::SnapshotInfo*);
860e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#endif
8619e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
8629e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    virtual void sweep(HeapStats*);
8639e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    virtual void postSweepProcessing();
8649e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
86509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual void clearFreeLists();
866197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    virtual void clearLiveAndMarkDead();
8679e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
8689e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    virtual void makeConsistentForSweeping();
8699e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
870197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT)
8719e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    virtual bool isConsistentForSweeping();
8729e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
87309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual void getScannedStats(HeapStats&);
87409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif
87509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
87609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ThreadState* threadState() { return m_threadState; }
87709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    HeapStats& stats() { return m_threadState->stats(); }
878f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    void flushHeapContainsCache()
879f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    {
880f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)        m_threadState->heapContainsCache()->flush();
881f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    }
88209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
88309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    inline Address allocate(size_t, const GCInfo*);
88409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void addToFreeList(Address, size_t);
88509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    inline static size_t roundedAllocationSize(size_t size)
88609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
88709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return allocationSizeFromSize(size) - sizeof(Header);
88809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
88909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
8909e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    virtual void prepareHeapForTermination();
8919e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
8929e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    virtual int normalPageCount() { return m_numberOfNormalPages; }
8939e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
8949e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    virtual BaseHeap* split(int numberOfNormalPages);
8959e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    virtual void merge(BaseHeap* splitOffBase);
8969e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
897197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    void removePageFromHeap(HeapPage<Header>*);
89809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
8997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    PLATFORM_EXPORT void promptlyFreeObject(Header*);
9007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
901197021e6b966cfb06891637935ef33fff06433d1Ben Murdochprivate:
902197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    void addPageToHeap(const GCInfo*);
903a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    PLATFORM_EXPORT Address outOfLineAllocate(size_t, const GCInfo*);
90409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static size_t allocationSizeFromSize(size_t);
905a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    PLATFORM_EXPORT Address allocateLargeObject(size_t, const GCInfo*);
90609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    Address currentAllocationPoint() const { return m_currentAllocationPoint; }
90709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    size_t remainingAllocationSize() const { return m_remainingAllocationSize; }
90809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    bool ownsNonEmptyAllocationArea() const { return currentAllocationPoint() && remainingAllocationSize(); }
90909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void setAllocationPoint(Address point, size_t size)
91009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
91109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        ASSERT(!point || heapPageFromAddress(point));
91209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        ASSERT(size <= HeapPage<Header>::payloadSize());
91309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        m_currentAllocationPoint = point;
91409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        m_remainingAllocationSize = size;
91509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
91609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void ensureCurrentAllocation(size_t, const GCInfo*);
91709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    bool allocateFromFreeList(size_t);
91809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
91909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void freeLargeObject(LargeHeapObject<Header>*, LargeHeapObject<Header>**);
92009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void allocatePage(const GCInfo*);
92109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
9229e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)#if ENABLE(ASSERT)
9239e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    bool pagesToBeSweptContains(Address);
9249e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    bool pagesAllocatedDuringSweepingContains(Address);
9259e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)#endif
9269e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
9279e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    void sweepNormalPages(HeapStats*);
9289e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    void sweepLargePages(HeapStats*);
9297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    bool coalesce(size_t);
9309e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
93109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    Address m_currentAllocationPoint;
93209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    size_t m_remainingAllocationSize;
93309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
93409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    HeapPage<Header>* m_firstPage;
93509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    LargeHeapObject<Header>* m_firstLargeHeapObject;
93609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
9379e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    HeapPage<Header>* m_firstPageAllocatedDuringSweeping;
9389e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    HeapPage<Header>* m_lastPageAllocatedDuringSweeping;
9399e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
9409e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    // Merge point for parallel sweep.
9419e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    HeapPage<Header>* m_mergePoint;
9429e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
94309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    int m_biggestFreeListIndex;
9449e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
94509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ThreadState* m_threadState;
94609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
94709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // All FreeListEntries in the nth list have size >= 2^n.
94809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    FreeListEntry* m_freeLists[blinkPageSizeLog2];
9499e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    FreeListEntry* m_lastFreeListEntries[blinkPageSizeLog2];
95009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
951197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // Index into the page pools. This is used to ensure that the pages of the
952197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // same type go into the correct page pool and thus avoid type confusion.
953197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    int m_index;
9549e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
9559e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    int m_numberOfNormalPages;
9567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
9577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // The promptly freed count contains the number of promptly freed objects
9587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // since the last sweep or since it was manually reset to delay coalescing.
9597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    size_t m_promptlyFreedCount;
96009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
96109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
962a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochclass PLATFORM_EXPORT Heap {
9633c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdochpublic:
96409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static void init();
965a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    static void shutdown();
96610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    static void doShutdown();
96709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
968d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    static BaseHeapPage* contains(Address);
969d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    static BaseHeapPage* contains(void* pointer) { return contains(reinterpret_cast<Address>(pointer)); }
970d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    static BaseHeapPage* contains(const void* pointer) { return contains(const_cast<void*>(pointer)); }
971197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT)
972197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static bool containedInHeapOrOrphanedPage(void*);
973197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#endif
97409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
97509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Push a trace callback on the marking stack.
9767242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    static void pushTraceCallback(CallbackStack*, void* containerObject, TraceCallback);
9777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
9787242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // Push a trace callback on the post-marking callback stack. These callbacks
9797242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // are called after normal marking (including ephemeron iteration).
9807242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    static void pushPostMarkingCallback(void*, TraceCallback);
98109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
982d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Add a weak pointer callback to the weak callback work list. General
983d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // object pointer callbacks are added to a thread local weak callback work
984d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // list and the callback is called on the thread that owns the object, with
985d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // the closure pointer as an argument. Most of the time, the closure and
986d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // the containerObject can be the same thing, but the containerObject is
987d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // constrained to be on the heap, since the heap is used to identify the
988d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // correct thread.
989d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    static void pushWeakObjectPointerCallback(void* closure, void* containerObject, WeakPointerCallback);
990d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
991d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Similar to the more general pushWeakObjectPointerCallback, but cell
992d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // pointer callbacks are added to a static callback work list and the weak
993d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // callback is performed on the thread performing garbage collection. This
994d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // is OK because cells are just cleared and no deallocation can happen.
995d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    static void pushWeakCellPointerCallback(void** cell, WeakPointerCallback);
99609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
9977242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // Pop the top of a marking stack and call the callback with the visitor
99809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // and the object. Returns false when there is nothing more to do.
9997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    template<CallbackInvocationMode Mode> static bool popAndInvokeTraceCallback(CallbackStack*, Visitor*);
10007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
10017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // Remove an item from the post-marking callback stack and call
10027242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // the callback with the visitor and the object pointer. Returns
10037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // false when there is nothing more to do.
10047242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    static bool popAndInvokePostMarkingCallback(Visitor*);
100509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1006d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Remove an item from the weak callback work list and call the callback
1007d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // with the visitor and the closure pointer. Returns false when there is
1008d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // nothing more to do.
100909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static bool popAndInvokeWeakPointerCallback(Visitor*);
101009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1011197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // Register an ephemeron table for fixed-point iteration.
1012197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static void registerWeakTable(void* containerObject, EphemeronCallback, EphemeronCallback);
1013197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT)
1014197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static bool weakTableRegistered(const void*);
1015197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#endif
1016197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
10177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    template<typename T, typename HeapTraits> static Address allocate(size_t);
10187242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // FIXME: remove this once c++11 is allowed everywhere:
10197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    template<typename T> static Address allocate(size_t);
10207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
102109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    template<typename T> static Address reallocate(void* previous, size_t);
102209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
10237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    static void collectGarbage(ThreadState::StackState, ThreadState::CauseOfGC = ThreadState::NormalGC);
1024197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static void collectGarbageForTerminatingThread(ThreadState*);
1025a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    static void collectAllGarbage();
10267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    static void processMarkingStackEntries(int* numberOfMarkingThreads);
10277242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    static void processMarkingStackOnMultipleThreads();
10287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    static void processMarkingStackInParallel();
1029c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    template<CallbackInvocationMode Mode> static void processMarkingStack();
10307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    static void postMarkingProcessing();
10317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    static void globalWeakProcessing();
1032a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    static void setForcePreciseGCForTesting();
103309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
103409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static void prepareForGC();
103509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
103609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Conservatively checks whether an address is a pointer in any of the thread
103709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // heaps. If so marks the object pointed to as live.
103809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static Address checkAndMarkPointer(Visitor*, Address);
103909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1040e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILE_MARKING)
1041f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    // Dump the path to specified object on the next GC. This method is to be invoked from GDB.
1042f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    static void dumpPathToObjectOnNextGC(void* p);
1043f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
1044f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    // Forcibly find GCInfo of the object at Address.
1045f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    // This is slow and should only be used for debug purposes.
1046f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    // It involves finding the heap page and scanning the heap page for an object header.
1047f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    static const GCInfo* findGCInfo(Address);
10485d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
10495d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    static String createBacktraceString();
1050f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#endif
1051f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
105209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Collect heap stats for all threads attached to the Blink
105309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // garbage collector. Should only be called during garbage
105409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // collection where threads are known to be at safe points.
105509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static void getStats(HeapStats*);
105609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1057f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    static void getHeapSpaceSize(uint64_t*, uint64_t*);
1058f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
10599e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    static void makeConsistentForSweeping();
10609e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
10619e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)#if ENABLE(ASSERT)
10629e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    static bool isConsistentForSweeping();
10639e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)#endif
106409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1065f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    static void flushHeapDoesNotContainCache();
1066f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    static bool heapDoesNotContainCacheIsEmpty() { return s_heapDoesNotContainCache->isEmpty(); }
1067f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)
1068d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // Return true if the last GC found a pointer into a heap page
1069d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // during conservative scanning.
1070d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    static bool lastGCWasConservative() { return s_lastGCWasConservative; }
1071d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
1072197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static FreePagePool* freePagePool() { return s_freePagePool; }
1073197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static OrphanedPagePool* orphanedPagePool() { return s_orphanedPagePool; }
1074197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
1075f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)private:
1076d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    static Visitor* s_markingVisitor;
10777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    static Vector<OwnPtr<blink::WebThread> >* s_markingThreads;
107809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static CallbackStack* s_markingStack;
10797242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    static CallbackStack* s_postMarkingCallbackStack;
108009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static CallbackStack* s_weakCallbackStack;
1081197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static CallbackStack* s_ephemeronStack;
1082f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    static HeapDoesNotContainCache* s_heapDoesNotContainCache;
108310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    static bool s_shutdownCalled;
1084d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    static bool s_lastGCWasConservative;
1085197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static FreePagePool* s_freePagePool;
1086197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static OrphanedPagePool* s_orphanedPagePool;
1087f523d2789ac2f83c4eca0ee4d5161bfdb5f2d052Torne (Richard Coles)    friend class ThreadState;
108809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
108909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
109009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// The NoAllocationScope class is used in debug mode to catch unwanted
109109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// allocations. E.g. allocations during GC.
109209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<ThreadAffinity Affinity>
109309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class NoAllocationScope {
109409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)public:
109509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    NoAllocationScope() : m_active(true) { enter(); }
109609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
109709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    explicit NoAllocationScope(bool active) : m_active(active) { enter(); }
109809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
109909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    NoAllocationScope(const NoAllocationScope& other) : m_active(other.m_active) { enter(); }
110009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
110109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    NoAllocationScope& operator=(const NoAllocationScope& other)
110209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
110309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        release();
110409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        m_active = other.m_active;
110509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        enter();
110609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return *this;
110709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
110809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
110909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ~NoAllocationScope() { release(); }
111009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
111109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void release()
111209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
111309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (m_active) {
111409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            ThreadStateFor<Affinity>::state()->leaveNoAllocationScope();
111509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            m_active = false;
111609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
111709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
111809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
111909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)private:
112009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void enter() const
112109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
112209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (m_active)
112309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            ThreadStateFor<Affinity>::state()->enterNoAllocationScope();
112409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
112509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
112609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    bool m_active;
112709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
112809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
112909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Base class for objects allocated in the Blink garbage-collected
113009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// heap.
113109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)//
113209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Defines a 'new' operator that allocates the memory in the
113309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// heap. 'delete' should not be called on objects that inherit from
113409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// GarbageCollected.
113509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)//
113609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Instances of GarbageCollected will *NOT* get finalized. Their
113709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// destructor will not be called. Therefore, only classes that have
113809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// trivial destructors with no semantic meaning (including all their
113909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// subclasses) should inherit from GarbageCollected. If there are
114009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// non-trival destructors in a given class or any of its subclasses,
114109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// GarbageCollectedFinalized should be used which guarantees that the
114209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// destructor is called on an instance when the garbage collector
114309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// determines that it is no longer reachable.
114409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T>
114509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class GarbageCollected {
114609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    WTF_MAKE_NONCOPYABLE(GarbageCollected);
114709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
114809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // For now direct allocation of arrays on the heap is not allowed.
114909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void* operator new[](size_t size);
11506f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch#if OS(WIN) && COMPILER(MSVC)
11516f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    // Due to some quirkiness in the MSVC compiler we have to provide
11526f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    // the delete[] operator in the GarbageCollected subclasses as it
11536f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    // is called when a class is exported in a DLL.
11546f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochprotected:
11556f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    void operator delete[](void* p)
11566f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    {
11576f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        ASSERT_NOT_REACHED();
11586f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    }
11596f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch#else
116009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void operator delete[](void* p);
11616f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch#endif
116209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)public:
1163d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    typedef T GarbageCollectedBase;
1164d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
116509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void* operator new(size_t size)
116609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
116709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return Heap::allocate<T>(size);
116809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
116909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
117009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void operator delete(void* p)
117109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
117209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        ASSERT_NOT_REACHED();
117309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
117409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
117509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)protected:
117609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    GarbageCollected()
117709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
117809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
117909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
118009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
118109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Base class for objects allocated in the Blink garbage-collected
118209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// heap.
118309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)//
118409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Defines a 'new' operator that allocates the memory in the
118509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// heap. 'delete' should not be called on objects that inherit from
118609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// GarbageCollected.
118709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)//
118809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Instances of GarbageCollectedFinalized will have their destructor
118909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// called when the garbage collector determines that the object is no
119009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// longer reachable.
119109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T>
119209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class GarbageCollectedFinalized : public GarbageCollected<T> {
119309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    WTF_MAKE_NONCOPYABLE(GarbageCollectedFinalized);
119409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
119509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)protected:
119643e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    // finalizeGarbageCollectedObject is called when the object is
119743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    // freed from the heap. By default finalization means calling the
119843e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    // destructor on the object. finalizeGarbageCollectedObject can be
119943e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    // overridden to support calling the destructor of a
120043e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    // subclass. This is useful for objects without vtables that
120143e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    // require explicit dispatching. The name is intentionally a bit
120243e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    // long to make name conflicts less likely.
120343e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    void finalizeGarbageCollectedObject()
120409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
120509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        static_cast<T*>(this)->~T();
120609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
120709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
120809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    GarbageCollectedFinalized() { }
120909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ~GarbageCollectedFinalized() { }
121009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
121109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    template<typename U> friend struct HasFinalizer;
121209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    template<typename U, bool> friend struct FinalizerTraitImpl;
121309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
121409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
121509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Base class for objects that are in the Blink garbage-collected heap
121609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// and are still reference counted.
121709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)//
121809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// This class should be used sparingly and only to gradually move
121909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// objects from being reference counted to being managed by the blink
122009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// garbage collector.
122109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)//
122209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// While the current reference counting keeps one of these objects
122309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// alive it will have a Persistent handle to itself allocated so we
122409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// will not reclaim the memory. When the reference count reaches 0 the
122509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// persistent handle will be deleted. When the garbage collector
122609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// determines that there are no other references to the object it will
122709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// be reclaimed and the destructor of the reclaimed object will be
122809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// called at that time.
122909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T>
123009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class RefCountedGarbageCollected : public GarbageCollectedFinalized<T> {
123109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    WTF_MAKE_NONCOPYABLE(RefCountedGarbageCollected);
123209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
123309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)public:
123409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RefCountedGarbageCollected()
123509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        : m_refCount(1)
123609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
1237f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        makeKeepAlive();
123809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
123909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
124009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Implement method to increase reference count for use with
124109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // RefPtrs.
124209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    //
124309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // In contrast to the normal WTF::RefCounted, the reference count
124409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // can reach 0 and increase again. This happens in the following
124509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // scenario:
124609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    //
124709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // (1) The reference count becomes 0, but members, persistents, or
124809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    //     on-stack pointers keep references to the object.
124909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    //
125009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // (2) The pointer is assigned to a RefPtr again and the reference
125109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    //     count becomes 1.
125209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    //
125309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // In this case, we have to resurrect m_keepAlive.
125409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void ref()
125509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
125609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (UNLIKELY(!m_refCount)) {
125709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            ASSERT(ThreadStateFor<ThreadingTrait<T>::Affinity>::state()->contains(reinterpret_cast<Address>(this)));
1258f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            makeKeepAlive();
125909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
126009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        ++m_refCount;
126109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
126209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
126309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Implement method to decrease reference count for use with
126409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // RefPtrs.
126509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    //
126609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // In contrast to the normal WTF::RefCounted implementation, the
126709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // object itself is not deleted when the reference count reaches
126809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // 0. Instead, the keep-alive persistent handle is deallocated so
126909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // that the object can be reclaimed when the garbage collector
127009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // determines that there are no other references to the object.
127109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void deref()
127209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
127309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        ASSERT(m_refCount > 0);
127409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (!--m_refCount) {
127509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            delete m_keepAlive;
127609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            m_keepAlive = 0;
127709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
127809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
127909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
128009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    bool hasOneRef()
128109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
128209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return m_refCount == 1;
128309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
128409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
128509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)protected:
128609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ~RefCountedGarbageCollected() { }
128709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
128809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)private:
1289f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    void makeKeepAlive()
1290f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    {
1291f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        ASSERT(!m_keepAlive);
1292f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        m_keepAlive = new Persistent<T>(static_cast<T*>(this));
1293f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    }
1294f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
129509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    int m_refCount;
129609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    Persistent<T>* m_keepAlive;
129709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
129809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
129909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T>
130009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)T* adoptRefCountedGarbageCollected(T* ptr)
130109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
130209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ASSERT(ptr->hasOneRef());
130309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ptr->deref();
130409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    WTF::adopted(ptr);
130509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return ptr;
130609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
130709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1308a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// Classes that contain heap references but aren't themselves heap
1309a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// allocated, have some extra macros available which allows their use
1310a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// to be restricted to cases where the garbage collector is able
1311a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// to discover their heap references.
1312a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch//
1313a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// STACK_ALLOCATED(): Use if the object is only stack allocated. Heap objects
1314a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// should be in Members but you do not need the trace method as they are on
1315a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// the stack. (Down the line these might turn in to raw pointers, but for
1316a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// now Members indicates that we have thought about them and explicitly
1317a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// taken care of them.)
1318a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch//
1319a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// DISALLOW_ALLOCATION(): Cannot be allocated with new operators but can
1320a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// be a part object. If it has Members you need a trace method and the
1321a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// containing object needs to call that trace method.
1322a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch//
1323a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// ALLOW_ONLY_INLINE_ALLOCATION(): Allows only placement new operator.
1324a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// This disallows general allocation of this object but allows to put
1325a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// the object as a value object in collections. If these have Members you
1326a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// need to have a trace method. That trace method will be called
1327a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// automatically by the Heap collections.
1328a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch//
132909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#if COMPILER_SUPPORTS(CXX_DELETED_FUNCTIONS)
133007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch#define DISALLOW_ALLOCATION()                                   \
133107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    private:                                                    \
133207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        void* operator new(size_t) = delete;                    \
133307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        void* operator new(size_t, NotNullTag, void*) = delete; \
133407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        void* operator new(size_t, void*) = delete;
133507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
133607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch#define ALLOW_ONLY_INLINE_ALLOCATION()                                              \
133707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    public:                                                                         \
133807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        void* operator new(size_t, NotNullTag, void* location) { return location; } \
133907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        void* operator new(size_t, void* location) { return location; }             \
134007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    private:                                                                        \
134109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        void* operator new(size_t) = delete;
134207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
1343a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#define STATIC_ONLY(Type) \
1344a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    private:              \
1345a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        Type() = delete;
1346a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
134709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#else
134807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
134907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch#define DISALLOW_ALLOCATION()                          \
135007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    private:                                           \
135107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        void* operator new(size_t);                    \
135207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        void* operator new(size_t, NotNullTag, void*); \
135307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        void* operator new(size_t, void*)
135409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
135509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#define ALLOW_ONLY_INLINE_ALLOCATION()                                              \
135609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    public:                                                                         \
135709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        void* operator new(size_t, NotNullTag, void* location) { return location; } \
135809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        void* operator new(size_t, void* location) { return location; }             \
135907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    private:                                                                        \
136007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        void* operator new(size_t);
136107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
1362a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#define STATIC_ONLY(Type)  \
1363a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    private:               \
1364a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        Type();
1365a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
136607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch#endif
136707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
136809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1369d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)// These macros insert annotations that the Blink GC plugin for clang uses for
1370d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)// verification. STACK_ALLOCATED is used to declare that objects of this type
1371d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)// are always stack allocated. GC_PLUGIN_IGNORE is used to make the plugin
1372d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)// ignore a particular class or field when checking for proper usage. When using
1373d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)// GC_PLUGIN_IGNORE a bug-number should be provided as an argument where the
1374d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)// bug describes what needs to happen to remove the GC_PLUGIN_IGNORE again.
1375f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#if COMPILER(CLANG)
137607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch#define STACK_ALLOCATED()                                       \
137707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    private:                                                    \
137807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        __attribute__((annotate("blink_stack_allocated")))      \
137907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        void* operator new(size_t) = delete;                    \
138007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        void* operator new(size_t, NotNullTag, void*) = delete; \
138107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        void* operator new(size_t, void*) = delete;
138207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
1383d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#define GC_PLUGIN_IGNORE(bug)                           \
1384d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    __attribute__((annotate("blink_gc_plugin_ignore")))
1385d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#else
1386d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#define STACK_ALLOCATED() DISALLOW_ALLOCATION()
1387d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#define GC_PLUGIN_IGNORE(bug)
1388d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#endif
1389d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
139009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)NO_SANITIZE_ADDRESS
139109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void HeapObjectHeader::checkHeader() const
139209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
1393197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT)
1394197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    BaseHeapPage* page = pageHeaderFromObject(this);
1395197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ASSERT(page->orphaned() || m_magic == magic);
1396197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#endif
139709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
139809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
139909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)Address HeapObjectHeader::payload()
140009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
140109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return reinterpret_cast<Address>(this) + objectHeaderSize;
140209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
140309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
140409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)size_t HeapObjectHeader::payloadSize()
140509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
140609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return size() - objectHeaderSize;
140709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
140809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
140909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)Address HeapObjectHeader::payloadEnd()
141009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
141109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return reinterpret_cast<Address>(this) + size();
141209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
141309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
141409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)NO_SANITIZE_ADDRESS
141509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void HeapObjectHeader::mark()
141609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
141709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    checkHeader();
14187242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // The use of atomic ops guarantees that the reads and writes are
14197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // atomic and that no memory operation reorderings take place.
14207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // Multiple threads can still read the old value and all store the
14217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // new value. However, the new value will be the same for all of
14227242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // the threads and the end result is therefore consistent.
14237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    unsigned size = asanUnsafeAcquireLoad(&m_size);
14247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    asanUnsafeReleaseStore(&m_size, size | markBitMask);
142509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
142609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
142709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)Address FinalizedHeapObjectHeader::payload()
142809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
142909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return reinterpret_cast<Address>(this) + finalizedHeaderSize;
143009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
143109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
143209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)size_t FinalizedHeapObjectHeader::payloadSize()
143309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
143409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return size() - finalizedHeaderSize;
143509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
143609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
143709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename Header>
143809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)size_t ThreadHeap<Header>::allocationSizeFromSize(size_t size)
143909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
144009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Check the size before computing the actual allocation size. The
144109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // allocation size calculation can overflow for large sizes and
144209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // the check therefore has to happen before any calculation on the
144309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // size.
144409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RELEASE_ASSERT(size < maxHeapObjectSize);
144509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
144609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Add space for header.
144709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    size_t allocationSize = size + sizeof(Header);
144809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Align size with allocation granularity.
144909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    allocationSize = (allocationSize + allocationMask) & ~allocationMask;
145009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return allocationSize;
145109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
145209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
145309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename Header>
145409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)Address ThreadHeap<Header>::allocate(size_t size, const GCInfo* gcInfo)
145509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
145609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    size_t allocationSize = allocationSizeFromSize(size);
145709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    bool isLargeObject = allocationSize > blinkPageSize / 2;
145809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (isLargeObject)
145909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return allocateLargeObject(allocationSize, gcInfo);
146009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (m_remainingAllocationSize < allocationSize)
146109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return outOfLineAllocate(size, gcInfo);
146209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    Address headerAddress = m_currentAllocationPoint;
146309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_currentAllocationPoint += allocationSize;
146409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_remainingAllocationSize -= allocationSize;
146509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    Header* header = new (NotNull, headerAddress) Header(allocationSize, gcInfo);
146609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    size_t payloadSize = allocationSize - sizeof(Header);
146709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    stats().increaseObjectSpace(payloadSize);
146809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    Address result = headerAddress + sizeof(*header);
146909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask));
147009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Unpoison the memory used for the object (payload).
147109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ASAN_UNPOISON_MEMORY_REGION(result, payloadSize);
1472197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT) || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER)
147309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    memset(result, 0, payloadSize);
1474197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#endif
147509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ASSERT(heapPageFromAddress(headerAddress + allocationSize - 1));
147609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return result;
147709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
147809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
14799e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)template<typename T, typename HeapTraits>
148009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)Address Heap::allocate(size_t size)
148109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
148209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state();
148309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ASSERT(state->isAllocationAllowed());
14849e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    const GCInfo* gcInfo = GCInfoTrait<T>::get();
14859e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    int heapIndex = HeapTraits::index(gcInfo->hasFinalizer());
14869e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    BaseHeap* heap = state->heap(heapIndex);
14879e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    return static_cast<typename HeapTraits::HeapType*>(heap)->allocate(size, gcInfo);
148809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
148909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
149009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T>
14917242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciAddress Heap::allocate(size_t size)
14927242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
14937242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return allocate<T, HeapTypeTrait<T> >(size);
14947242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
14957242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
14967242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccitemplate<typename T>
149709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)Address Heap::reallocate(void* previous, size_t size)
149809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
149909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!size) {
150009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // If the new size is 0 this is equivalent to either
150109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // free(previous) or malloc(0). In both cases we do
150209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // nothing and return 0.
150309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return 0;
150409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
150509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state();
150609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ASSERT(state->isAllocationAllowed());
15079e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    const GCInfo* gcInfo = GCInfoTrait<T>::get();
15089e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    int heapIndex = HeapTypeTrait<T>::index(gcInfo->hasFinalizer());
150909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // FIXME: Currently only supports raw allocation on the
151009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // GeneralHeap. Hence we assume the header is a
151109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // FinalizedHeapObjectHeader.
15129e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    ASSERT(heapIndex == GeneralHeap || heapIndex == GeneralHeapNonFinalized);
15139e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    BaseHeap* heap = state->heap(heapIndex);
15149e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    Address address = static_cast<typename HeapTypeTrait<T>::HeapType*>(heap)->allocate(size, gcInfo);
151509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!previous) {
151609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // This is equivalent to malloc(size).
151709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return address;
151809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
151909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    FinalizedHeapObjectHeader* previousHeader = FinalizedHeapObjectHeader::fromPayload(previous);
152009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ASSERT(!previousHeader->hasFinalizer());
15219e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    ASSERT(previousHeader->gcInfo() == gcInfo);
152209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    size_t copySize = previousHeader->payloadSize();
152309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (copySize > size)
152409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        copySize = size;
152509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    memcpy(address, previous, copySize);
152609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return address;
152709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
152809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
152909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class HeapAllocatorQuantizer {
153009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)public:
153109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    template<typename T>
153209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static size_t quantizedSize(size_t count)
153309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
153409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        RELEASE_ASSERT(count <= kMaxUnquantizedAllocation / sizeof(T));
15359e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        return HeapIndexTrait<CollectionBackingHeap>::HeapType::roundedAllocationSize(count * sizeof(T));
153609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
153709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static const size_t kMaxUnquantizedAllocation = maxHeapObjectSize;
153809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
153909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1540323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)// This is a static-only class used as a trait on collections to make them heap allocated.
1541323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)// However see also HeapListHashSetAllocator.
154209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class HeapAllocator {
154309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)public:
154409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    typedef HeapAllocatorQuantizer Quantizer;
1545c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    typedef blink::Visitor Visitor;
154609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static const bool isGarbageCollected = true;
154709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
154809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    template <typename Return, typename Metadata>
154909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static Return backingMalloc(size_t size)
155009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
15519e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        return reinterpret_cast<Return>(Heap::allocate<Metadata, HeapIndexTrait<CollectionBackingHeap> >(size));
155209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
155309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    template <typename Return, typename Metadata>
155409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static Return zeroedBackingMalloc(size_t size)
155509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
15569e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        return backingMalloc<Return, Metadata>(size);
155709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
155809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    template <typename Return, typename Metadata>
155909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static Return malloc(size_t size)
156009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
156109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return reinterpret_cast<Return>(Heap::allocate<Metadata>(size));
156209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
15637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    PLATFORM_EXPORT static void backingFree(void* address);
15647242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
156509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static void free(void* address) { }
156609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    template<typename T>
156709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static void* newArray(size_t bytes)
156809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
156909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        ASSERT_NOT_REACHED();
157009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return 0;
157109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
157209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
157309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static void deleteArray(void* ptr)
157409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
157509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        ASSERT_NOT_REACHED();
157609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
157709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1578e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    static bool isAllocationAllowed()
1579e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    {
1580e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        return ThreadState::current()->isAllocationAllowed();
1581e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    }
1582e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
158309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static void markUsingGCInfo(Visitor* visitor, const void* buffer)
158409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
158509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        visitor->mark(buffer, FinalizedHeapObjectHeader::fromPayload(buffer)->traceCallback());
158609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
158709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1588323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    static void markNoTracing(Visitor* visitor, const void* t) { visitor->markNoTracing(t); }
158909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
159009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    template<typename T, typename Traits>
159109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static void trace(Visitor* visitor, T& t)
159209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
1593197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        CollectionBackingTraceTrait<WTF::ShouldBeTraced<Traits>::value, Traits::weakHandlingFlag, WTF::WeakPointersActWeak, T, Traits>::trace(visitor, t);
159409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
159509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
15967242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    static void registerDelayedMarkNoTracing(Visitor* visitor, const void* object)
15977242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    {
15987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        visitor->registerDelayedMarkNoTracing(object);
15997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
16007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1601d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    static void registerWeakMembers(Visitor* visitor, const void* closure, const void* object, WeakPointerCallback callback)
160209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
1603d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        visitor->registerWeakMembers(closure, object, callback);
160409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
160509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1606197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static void registerWeakTable(Visitor* visitor, const void* closure, EphemeronCallback iterationCallback, EphemeronCallback iterationDoneCallback)
1607197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    {
1608197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        visitor->registerWeakTable(closure, iterationCallback, iterationDoneCallback);
1609197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
1610197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
1611197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT)
1612197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static bool weakTableRegistered(Visitor* visitor, const void* closure)
1613197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    {
1614197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return visitor->weakTableRegistered(closure);
1615197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
1616197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#endif
1617197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
161809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    template<typename T>
161909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    struct ResultType {
162009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        typedef T* Type;
162109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    };
162209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
162309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // The WTF classes use Allocator::VectorBackingHelper in order to find a
162409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // class to template their backing allocation operation on. For off-heap
162509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // allocations the VectorBackingHelper is a dummy class, since the class is
162609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // not used during allocation of backing. For on-heap allocations this
162709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // typedef ensures that the allocation is done with the correct templated
162809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // instantiation of the allocation function. This ensures the correct GC
162909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // map is written when backing allocations take place.
163009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    template<typename T, typename Traits>
163109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    struct VectorBackingHelper {
163209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        typedef HeapVectorBacking<T, Traits> Type;
163309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    };
163409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
163509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Like the VectorBackingHelper, but this type is used for HashSet and
163609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // HashMap, both of which are implemented using HashTable.
1637aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    template<typename Table>
163809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    struct HashTableBackingHelper {
1639aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch        typedef HeapHashTableBacking<Table> Type;
164009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    };
164109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
164209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    template<typename T>
164309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    struct OtherType {
164409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        typedef T* Type;
164509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    };
164609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
164709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    template<typename T>
164809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static T& getOther(T* other)
164909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
165009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return *other;
165109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
165209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
16537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    static void enterNoAllocationScope()
16547242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    {
16557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#if ENABLE(ASSERT)
16567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        ThreadStateFor<AnyThread>::state()->enterNoAllocationScope();
16577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#endif
16587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
16597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
16607242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    static void leaveNoAllocationScope()
16617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    {
16627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#if ENABLE(ASSERT)
16637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        ThreadStateFor<AnyThread>::state()->leaveNoAllocationScope();
16647242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#endif
16657242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
16667242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
166709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)private:
166809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    template<typename T, size_t u, typename V> friend class WTF::Vector;
166909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    template<typename T, typename U, typename V, typename W> friend class WTF::HashSet;
167009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    template<typename T, typename U, typename V, typename W, typename X, typename Y> friend class WTF::HashMap;
167109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
167209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1673323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)template<typename Value>
1674323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)static void traceListHashSetValue(Visitor* visitor, Value& value)
1675323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles){
1676323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // We use the default hash traits for the value in the node, because
1677323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // ListHashSet does not let you specify any specific ones.
1678323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // We don't allow ListHashSet of WeakMember, so we set that one false
1679323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // (there's an assert elsewhere), but we have to specify some value for the
1680197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // strongify template argument, so we specify WTF::WeakPointersActWeak,
1681323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // arbitrarily.
1682197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    CollectionBackingTraceTrait<WTF::ShouldBeTraced<WTF::HashTraits<Value> >::value, WTF::NoWeakHandlingInCollections, WTF::WeakPointersActWeak, Value, WTF::HashTraits<Value> >::trace(visitor, value);
1683323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)}
1684323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
1685323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)// The inline capacity is just a dummy template argument to match the off-heap
1686323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)// allocator.
1687323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)// This inherits from the static-only HeapAllocator trait class, but we do
1688323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)// declare pointers to instances. These pointers are always null, and no
1689323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)// objects are instantiated.
1690323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)template<typename ValueArg, size_t inlineCapacity>
1691323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)struct HeapListHashSetAllocator : public HeapAllocator {
1692323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    typedef HeapAllocator TableAllocator;
1693323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    typedef WTF::ListHashSetNode<ValueArg, HeapListHashSetAllocator> Node;
1694323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
1695323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)public:
1696323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    class AllocatorProvider {
1697323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    public:
1698323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        // For the heap allocation we don't need an actual allocator object, so we just
1699323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        // return null.
1700323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        HeapListHashSetAllocator* get() const { return 0; }
1701323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
1702323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        // No allocator object is needed.
1703323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        void createAllocatorIfNeeded() { }
1704323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
1705323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        // There is no allocator object in the HeapListHashSet (unlike in
1706323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        // the regular ListHashSet) so there is nothing to swap.
1707323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        void swap(AllocatorProvider& other) { }
1708323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    };
1709323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
1710323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    void deallocate(void* dummy) { }
1711323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
1712323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // This is not a static method even though it could be, because it
1713323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // needs to match the one that the (off-heap) ListHashSetAllocator
1714323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // has. The 'this' pointer will always be null.
1715323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    void* allocateNode()
1716323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    {
1717323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        COMPILE_ASSERT(!WTF::IsWeak<ValueArg>::value, WeakPointersInAListHashSetWillJustResultInNullEntriesInTheSetThatsNotWhatYouWantConsiderUsingLinkedHashSetInstead);
1718323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        return malloc<void*, Node>(sizeof(Node));
1719323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    }
1720323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
1721323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    static void traceValue(Visitor* visitor, Node* node)
1722323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    {
1723323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        traceListHashSetValue(visitor, node->m_value);
1724323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    }
1725323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)};
1726323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
172709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// FIXME: These should just be template aliases:
172809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)//
172909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// template<typename T, size_t inlineCapacity = 0>
173009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// using HeapVector = Vector<T, inlineCapacity, HeapAllocator>;
173109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)//
173209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// as soon as all the compilers we care about support that.
173309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// MSVC supports it only in MSVC 2013.
173409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<
173509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    typename KeyArg,
173609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    typename MappedArg,
173709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    typename HashArg = typename DefaultHash<KeyArg>::Hash,
173809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    typename KeyTraitsArg = HashTraits<KeyArg>,
173909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    typename MappedTraitsArg = HashTraits<MappedArg> >
174009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class HeapHashMap : public HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, HeapAllocator> { };
174109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
174209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<
174309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    typename ValueArg,
174409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    typename HashArg = typename DefaultHash<ValueArg>::Hash,
174509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    typename TraitsArg = HashTraits<ValueArg> >
174609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class HeapHashSet : public HashSet<ValueArg, HashArg, TraitsArg, HeapAllocator> { };
174709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
17486f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochtemplate<
17496f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    typename ValueArg,
17506f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    typename HashArg = typename DefaultHash<ValueArg>::Hash,
17516f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    typename TraitsArg = HashTraits<ValueArg> >
17526f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochclass HeapLinkedHashSet : public LinkedHashSet<ValueArg, HashArg, TraitsArg, HeapAllocator> { };
17536f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
1754f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liutemplate<
1755323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    typename ValueArg,
1756323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    size_t inlineCapacity = 0, // The inlineCapacity is just a dummy to match ListHashSet (off-heap).
1757323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    typename HashArg = typename DefaultHash<ValueArg>::Hash>
1758323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)class HeapListHashSet : public ListHashSet<ValueArg, inlineCapacity, HashArg, HeapListHashSetAllocator<ValueArg, inlineCapacity> > { };
1759323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
1760323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)template<
1761f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    typename Value,
1762f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    typename HashFunctions = typename DefaultHash<Value>::Hash,
1763f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    typename Traits = HashTraits<Value> >
1764f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liuclass HeapHashCountedSet : public HashCountedSet<Value, HashFunctions, Traits, HeapAllocator> { };
1765f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
176609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T, size_t inlineCapacity = 0>
176709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class HeapVector : public Vector<T, inlineCapacity, HeapAllocator> {
176809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)public:
176909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    HeapVector() { }
177009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
177109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    explicit HeapVector(size_t size) : Vector<T, inlineCapacity, HeapAllocator>(size)
177209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
177309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
177409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1775d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    HeapVector(size_t size, const T& val) : Vector<T, inlineCapacity, HeapAllocator>(size, val)
1776d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    {
1777d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
1778d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
177909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    template<size_t otherCapacity>
178009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    HeapVector(const HeapVector<T, otherCapacity>& other)
178109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        : Vector<T, inlineCapacity, HeapAllocator>(other)
178209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
178309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
178409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
178509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    template<typename U>
178609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    void append(const U& other)
178709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
178809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        Vector<T, inlineCapacity, HeapAllocator>::append(other);
178909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
179009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
179109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    template<typename U, size_t otherCapacity>
1792d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    void appendVector(const HeapVector<U, otherCapacity>& other)
179309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
179409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        const Vector<U, otherCapacity, HeapAllocator>& otherVector = other;
1795d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        Vector<T, inlineCapacity, HeapAllocator>::appendVector(otherVector);
179609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
179709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
179809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1799a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochtemplate<typename T, size_t inlineCapacity = 0>
1800a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochclass HeapDeque : public Deque<T, inlineCapacity, HeapAllocator> {
1801a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochpublic:
1802a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    HeapDeque() { }
1803a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1804a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    explicit HeapDeque(size_t size) : Deque<T, inlineCapacity, HeapAllocator>(size)
1805a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    {
1806a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
1807a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1808a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    HeapDeque(size_t size, const T& val) : Deque<T, inlineCapacity, HeapAllocator>(size, val)
1809a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    {
1810a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
1811a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1812a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // FIXME: Doesn't work if there is an inline buffer, due to crbug.com/360572
1813a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    HeapDeque<T, 0>& operator=(const HeapDeque& other)
1814a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    {
1815a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        HeapDeque<T> copy(other);
1816a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        swap(copy);
1817a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return *this;
1818a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
1819a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1820a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // FIXME: Doesn't work if there is an inline buffer, due to crbug.com/360572
1821a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    inline void swap(HeapDeque& other)
1822a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    {
1823a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        Deque<T, inlineCapacity, HeapAllocator>::swap(other);
1824a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
1825a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1826a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    template<size_t otherCapacity>
1827a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    HeapDeque(const HeapDeque<T, otherCapacity>& other)
1828a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        : Deque<T, inlineCapacity, HeapAllocator>(other)
1829a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    {
1830a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
1831a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1832a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    template<typename U>
1833a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    void append(const U& other)
1834a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    {
1835a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        Deque<T, inlineCapacity, HeapAllocator>::append(other);
1836a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
1837a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch};
1838a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
18397242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccitemplate<typename T, size_t i>
18407242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciinline void swap(HeapVector<T, i>& a, HeapVector<T, i>& b) { a.swap(b); }
18417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccitemplate<typename T, size_t i>
18427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciinline void swap(HeapDeque<T, i>& a, HeapDeque<T, i>& b) { a.swap(b); }
18437242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccitemplate<typename T, typename U, typename V>
18447242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciinline void swap(HeapHashSet<T, U, V>& a, HeapHashSet<T, U, V>& b) { a.swap(b); }
18457242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccitemplate<typename T, typename U, typename V, typename W, typename X>
18467242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciinline void swap(HeapHashMap<T, U, V, W, X>& a, HeapHashMap<T, U, V, W, X>& b) { a.swap(b); }
18477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccitemplate<typename T, size_t i, typename U>
18487242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciinline void swap(HeapListHashSet<T, i, U>& a, HeapListHashSet<T, i, U>& b) { a.swap(b); }
18497242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccitemplate<typename T, typename U, typename V>
18507242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciinline void swap(HeapLinkedHashSet<T, U, V>& a, HeapLinkedHashSet<T, U, V>& b) { a.swap(b); }
18517242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccitemplate<typename T, typename U, typename V>
18527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciinline void swap(HeapHashCountedSet<T, U, V>& a, HeapHashCountedSet<T, U, V>& b) { a.swap(b); }
18537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
185409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T>
185509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)struct ThreadingTrait<Member<T> > {
185609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static const ThreadAffinity Affinity = ThreadingTrait<T>::Affinity;
18573c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch};
18585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
185909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T>
186009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)struct ThreadingTrait<WeakMember<T> > {
186109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static const ThreadAffinity Affinity = ThreadingTrait<T>::Affinity;
186209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
186309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
186409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename Key, typename Value, typename T, typename U, typename V>
1865aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdochstruct ThreadingTrait<HashMap<Key, Value, T, U, V, HeapAllocator> > {
186609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static const ThreadAffinity Affinity =
186709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        (ThreadingTrait<Key>::Affinity == MainThreadOnly)
186809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        && (ThreadingTrait<Value>::Affinity == MainThreadOnly) ? MainThreadOnly : AnyThread;
186909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
187009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1871d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)template<typename First, typename Second>
1872d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)struct ThreadingTrait<WTF::KeyValuePair<First, Second> > {
1873d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    static const ThreadAffinity Affinity =
1874d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        (ThreadingTrait<First>::Affinity == MainThreadOnly)
1875d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        && (ThreadingTrait<Second>::Affinity == MainThreadOnly) ? MainThreadOnly : AnyThread;
1876d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)};
1877d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
187809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T, typename U, typename V>
1879aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdochstruct ThreadingTrait<HashSet<T, U, V, HeapAllocator> > {
188009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static const ThreadAffinity Affinity = ThreadingTrait<T>::Affinity;
188109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
188209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
188309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
188409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T, size_t inlineCapacity>
188509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)struct ThreadingTrait<Vector<T, inlineCapacity, HeapAllocator> > {
188609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static const ThreadAffinity Affinity = ThreadingTrait<T>::Affinity;
188709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
188809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
188909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T, typename Traits>
189009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)struct ThreadingTrait<HeapVectorBacking<T, Traits> > {
189109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static const ThreadAffinity Affinity = ThreadingTrait<T>::Affinity;
189209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
189309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1894a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochtemplate<typename T, size_t inlineCapacity>
1895a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct ThreadingTrait<Deque<T, inlineCapacity, HeapAllocator> > {
1896a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    static const ThreadAffinity Affinity = ThreadingTrait<T>::Affinity;
1897a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch};
1898a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1899f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liutemplate<typename T, typename U, typename V>
1900f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liustruct ThreadingTrait<HashCountedSet<T, U, V, HeapAllocator> > {
1901f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    static const ThreadAffinity Affinity = ThreadingTrait<T>::Affinity;
1902f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu};
1903f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
1904aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdochtemplate<typename Table>
1905aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdochstruct ThreadingTrait<HeapHashTableBacking<Table> > {
1906aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    typedef typename Table::KeyType Key;
1907aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    typedef typename Table::ValueType Value;
190809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static const ThreadAffinity Affinity =
190909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        (ThreadingTrait<Key>::Affinity == MainThreadOnly)
191009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        && (ThreadingTrait<Value>::Affinity == MainThreadOnly) ? MainThreadOnly : AnyThread;
191109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
191209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1913aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdochtemplate<typename T, typename U, typename V, typename W, typename X>
1914aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdochstruct ThreadingTrait<HeapHashMap<T, U, V, W, X> > : public ThreadingTrait<HashMap<T, U, V, W, X, HeapAllocator> > { };
1915aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch
1916aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdochtemplate<typename T, typename U, typename V>
1917aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdochstruct ThreadingTrait<HeapHashSet<T, U, V> > : public ThreadingTrait<HashSet<T, U, V, HeapAllocator> > { };
1918aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch
191909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T, size_t inlineCapacity>
192009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)struct ThreadingTrait<HeapVector<T, inlineCapacity> > : public ThreadingTrait<Vector<T, inlineCapacity, HeapAllocator> > { };
192109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1922a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochtemplate<typename T, size_t inlineCapacity>
1923a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct ThreadingTrait<HeapDeque<T, inlineCapacity> > : public ThreadingTrait<Deque<T, inlineCapacity, HeapAllocator> > { };
1924a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1925f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liutemplate<typename T, typename U, typename V>
1926f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liustruct ThreadingTrait<HeapHashCountedSet<T, U, V> > : public ThreadingTrait<HashCountedSet<T, U, V, HeapAllocator> > { };
1927f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
192809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// The standard implementation of GCInfoTrait<T>::get() just returns a static
1929f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// from the class T, but we can't do that for HashMap, HashSet, Vector, etc.
1930f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// because they are in WTF and know nothing of GCInfos. Instead we have a
1931f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// specialization of GCInfoTrait for these four classes here.
193209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
193309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename Key, typename Value, typename T, typename U, typename V>
193409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)struct GCInfoTrait<HashMap<Key, Value, T, U, V, HeapAllocator> > {
1935f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    static const GCInfo* get()
1936f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    {
1937f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        typedef HashMap<Key, Value, T, U, V, HeapAllocator> TargetType;
1938f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        static const GCInfo info = {
1939f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            TraceTrait<TargetType>::trace,
1940f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            0,
1941f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            false, // HashMap needs no finalizer.
1942d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            WTF::IsPolymorphic<TargetType>::value,
1943e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILING)
1944f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            TypenameStringTrait<TargetType>::get()
1945f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#endif
1946f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        };
1947f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        return &info;
1948f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    }
194909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
195009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
195109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T, typename U, typename V>
195209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)struct GCInfoTrait<HashSet<T, U, V, HeapAllocator> > {
1953f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    static const GCInfo* get()
1954f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    {
1955f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        typedef HashSet<T, U, V, HeapAllocator> TargetType;
1956f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        static const GCInfo info = {
1957f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            TraceTrait<TargetType>::trace,
1958f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            0,
1959f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            false, // HashSet needs no finalizer.
1960d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            WTF::IsPolymorphic<TargetType>::value,
1961e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILING)
1962f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            TypenameStringTrait<TargetType>::get()
1963f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#endif
1964f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        };
1965f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        return &info;
1966f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    }
196709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
196809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
19696f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochtemplate<typename T, typename U, typename V>
19706f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochstruct GCInfoTrait<LinkedHashSet<T, U, V, HeapAllocator> > {
1971f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    static const GCInfo* get()
1972f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    {
1973f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        typedef LinkedHashSet<T, U, V, HeapAllocator> TargetType;
1974f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        static const GCInfo info = {
1975f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            TraceTrait<TargetType>::trace,
1976f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            LinkedHashSet<T, U, V, HeapAllocator>::finalize,
1977f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            true, // Needs finalization. The anchor needs to unlink itself from the chain.
1978d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            WTF::IsPolymorphic<TargetType>::value,
1979e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILING)
1980f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            TypenameStringTrait<TargetType>::get()
1981f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#endif
1982f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        };
1983f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        return &info;
1984f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    }
1985323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)};
1986323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
1987323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)template<typename ValueArg, size_t inlineCapacity, typename U>
1988323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)struct GCInfoTrait<ListHashSet<ValueArg, inlineCapacity, U, HeapListHashSetAllocator<ValueArg, inlineCapacity> > > {
1989323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    static const GCInfo* get()
1990323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    {
1991323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        typedef WTF::ListHashSet<ValueArg, inlineCapacity, U, HeapListHashSetAllocator<ValueArg, inlineCapacity> > TargetType;
1992323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        static const GCInfo info = {
1993323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            TraceTrait<TargetType>::trace,
1994323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            0,
1995323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            false, // ListHashSet needs no finalization though its backing might.
1996323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            false, // no vtable.
1997e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILING)
1998323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            TypenameStringTrait<TargetType>::get()
1999323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)#endif
2000323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        };
2001323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        return &info;
2002323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    }
2003323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)};
2004323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
2005323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)template<typename T, typename Allocator>
2006323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)struct GCInfoTrait<WTF::ListHashSetNode<T, Allocator> > {
2007323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    static const GCInfo* get()
2008323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    {
2009323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        typedef WTF::ListHashSetNode<T, Allocator> TargetType;
2010323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        static const GCInfo info = {
2011323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            TraceTrait<TargetType>::trace,
2012323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            TargetType::finalize,
2013323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            WTF::HashTraits<T>::needsDestruction, // The node needs destruction if its data does.
2014323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            false, // no vtable.
2015e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILING)
2016323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            TypenameStringTrait<TargetType>::get()
2017323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)#endif
2018323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        };
2019323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        return &info;
2020323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    }
20216f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch};
20226f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
202309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T>
202409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)struct GCInfoTrait<Vector<T, 0, HeapAllocator> > {
2025f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    static const GCInfo* get()
2026f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    {
2027e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILING)
2028f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        typedef Vector<T, 0, HeapAllocator> TargetType;
2029323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)#endif
2030f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        static const GCInfo info = {
2031f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            TraceTrait<Vector<T, 0, HeapAllocator> >::trace,
2032f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            0,
2033f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            false, // Vector needs no finalizer if it has no inline capacity.
2034d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            WTF::IsPolymorphic<Vector<T, 0, HeapAllocator> >::value,
2035e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILING)
2036f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            TypenameStringTrait<TargetType>::get()
2037f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#endif
2038f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        };
2039f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        return &info;
2040f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    }
204109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
204209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
204309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T, size_t inlineCapacity>
204409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)struct FinalizerTrait<Vector<T, inlineCapacity, HeapAllocator> > : public FinalizerTraitImpl<Vector<T, inlineCapacity, HeapAllocator>, true> { };
204509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
204609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T, size_t inlineCapacity>
2047f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liustruct GCInfoTrait<Vector<T, inlineCapacity, HeapAllocator> > {
2048f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    static const GCInfo* get()
2049f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    {
2050f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        typedef Vector<T, inlineCapacity, HeapAllocator> TargetType;
2051f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        static const GCInfo info = {
2052f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            TraceTrait<TargetType>::trace,
2053f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            FinalizerTrait<TargetType>::finalize,
2054f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            // Finalizer is needed to destruct things stored in the inline capacity.
2055f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            inlineCapacity && VectorTraits<T>::needsDestruction,
2056d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            WTF::IsPolymorphic<TargetType>::value,
2057e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILING)
2058f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            TypenameStringTrait<TargetType>::get()
2059f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#endif
2060f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        };
2061f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        return &info;
2062f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    }
2063a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch};
2064a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
2065a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochtemplate<typename T>
2066a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct GCInfoTrait<Deque<T, 0, HeapAllocator> > {
2067f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    static const GCInfo* get()
2068f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    {
2069f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        typedef Deque<T, 0, HeapAllocator> TargetType;
2070f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        static const GCInfo info = {
2071f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            TraceTrait<TargetType>::trace,
2072f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            0,
2073f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            false, // Deque needs no finalizer if it has no inline capacity.
2074d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            WTF::IsPolymorphic<TargetType>::value,
2075e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILING)
2076f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            TypenameStringTrait<TargetType>::get()
2077f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#endif
2078f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        };
2079f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        return &info;
2080f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    }
2081a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    static const GCInfo info;
2082a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch};
2083a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
2084f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liutemplate<typename T, typename U, typename V>
2085f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liustruct GCInfoTrait<HashCountedSet<T, U, V, HeapAllocator> > {
2086f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    static const GCInfo* get()
2087f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    {
2088f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        typedef HashCountedSet<T, U, V, HeapAllocator> TargetType;
2089f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        static const GCInfo info = {
2090f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            TraceTrait<TargetType>::trace,
2091f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            0,
2092f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            false, // HashCountedSet is just a HashTable, and needs no finalizer.
2093d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            WTF::IsPolymorphic<TargetType>::value,
2094e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILING)
2095f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            TypenameStringTrait<TargetType>::get()
2096f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#endif
2097f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        };
2098f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        return &info;
2099f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    }
2100a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    static const GCInfo info;
2101a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch};
2102a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
2103a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochtemplate<typename T, size_t inlineCapacity>
2104a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct FinalizerTrait<Deque<T, inlineCapacity, HeapAllocator> > : public FinalizerTraitImpl<Deque<T, inlineCapacity, HeapAllocator>, true> { };
2105a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
2106a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochtemplate<typename T, size_t inlineCapacity>
2107f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liustruct GCInfoTrait<Deque<T, inlineCapacity, HeapAllocator> > {
2108f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    static const GCInfo* get()
2109f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    {
2110f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        typedef Deque<T, inlineCapacity, HeapAllocator> TargetType;
2111f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        static const GCInfo info = {
2112f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            TraceTrait<TargetType>::trace,
2113f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            FinalizerTrait<TargetType>::finalize,
2114f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            // Finalizer is needed to destruct things stored in the inline capacity.
2115f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            inlineCapacity && VectorTraits<T>::needsDestruction,
2116d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            WTF::IsPolymorphic<TargetType>::value,
2117e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILING)
2118f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            TypenameStringTrait<TargetType>::get()
2119f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#endif
2120f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        };
2121f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        return &info;
2122f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    }
212309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static const GCInfo info;
212409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
212509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
212609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T, typename Traits>
2127f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liustruct GCInfoTrait<HeapVectorBacking<T, Traits> > {
2128f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    static const GCInfo* get()
2129f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    {
2130f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        typedef HeapVectorBacking<T, Traits> TargetType;
2131f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        static const GCInfo info = {
2132f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            TraceTrait<TargetType>::trace,
2133f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            FinalizerTrait<TargetType>::finalize,
2134f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            Traits::needsDestruction,
2135f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            false, // We don't support embedded objects in HeapVectors with vtables.
2136e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILING)
2137f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            TypenameStringTrait<TargetType>::get()
2138f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#endif
2139f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        };
2140f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        return &info;
2141f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    }
214209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
214309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
2144aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdochtemplate<typename Table>
2145aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdochstruct GCInfoTrait<HeapHashTableBacking<Table> > {
2146f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    static const GCInfo* get()
2147f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    {
2148f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        typedef HeapHashTableBacking<Table> TargetType;
2149f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        static const GCInfo info = {
2150f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            TraceTrait<TargetType>::trace,
2151f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            HeapHashTableBacking<Table>::finalize,
2152f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            Table::ValueTraits::needsDestruction,
2153d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            WTF::IsPolymorphic<TargetType>::value,
2154e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#if ENABLE(GC_PROFILING)
2155f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            TypenameStringTrait<TargetType>::get()
2156f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#endif
2157f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        };
2158f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        return &info;
2159f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    }
216009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
216109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
2162c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
2163197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
2164197021e6b966cfb06891637935ef33fff06433d1Ben Murdochnamespace WTF {
21655d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
21665d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)// Catch-all for types that have a way to trace that don't have special
21675d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)// handling for weakness in collections. This means that if this type
21685d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)// contains WeakMember fields, they will simply be zeroed, but the entry
21695d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)// will not be removed from the collection. This always happens for
21705d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)// things in vectors, which don't currently support special handling of
21715d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)// weak elements.
21725d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)template<ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits>
2173197021e6b966cfb06891637935ef33fff06433d1Ben Murdochstruct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, T, Traits> {
2174c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    static bool trace(blink::Visitor* visitor, T& t)
21755d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    {
2176c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        blink::TraceTrait<T>::trace(visitor, &t);
2177197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return false;
21785d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    }
21795d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)};
21805d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
21815d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)// Catch-all for things that have HashTrait support for tracing with weakness.
21825d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)template<ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits>
2183197021e6b966cfb06891637935ef33fff06433d1Ben Murdochstruct TraceInCollectionTrait<WeakHandlingInCollections, strongify, T, Traits> {
2184c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    static bool trace(blink::Visitor* visitor, T& t)
21855d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    {
2186197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return Traits::traceInCollection(visitor, t, strongify);
21875d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    }
21885d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)};
21895d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
21905d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)// Vector backing that needs marking. We don't support weak members in vectors.
21915d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)template<ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits>
2192c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, blink::HeapVectorBacking<T, Traits>, void> {
2193c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    static bool trace(blink::Visitor* visitor, void* self)
219409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
219509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // The allocator can oversize the allocation a little, according to
219609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // the allocation granularity. The extra size is included in the
219709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // payloadSize call below, since there is nowhere to store the
219809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // originally allocated memory. This assert ensures that visiting the
219909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // last bit of memory can't cause trouble.
2200c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        COMPILE_ASSERT(!ShouldBeTraced<Traits>::value || sizeof(T) > blink::allocationGranularity || Traits::canInitializeWithMemset, HeapOverallocationCanCauseSpuriousVisits);
220109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
220209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        T* array = reinterpret_cast<T*>(self);
2203c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        blink::FinalizedHeapObjectHeader* header = blink::FinalizedHeapObjectHeader::fromPayload(self);
220409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // Use the payload size as recorded by the heap to determine how many
220509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // elements to mark.
220609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        size_t length = header->payloadSize() / sizeof(T);
220709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        for (size_t i = 0; i < length; i++)
2208c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            blink::CollectionBackingTraceTrait<ShouldBeTraced<Traits>::value, Traits::weakHandlingFlag, WeakPointersActStrong, T, Traits>::trace(visitor, array[i]);
2209197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return false;
221009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
221109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
221209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
2213323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)// Almost all hash table backings are visited with this specialization.
22146f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochtemplate<ShouldWeakPointersBeMarkedStrongly strongify, typename Table>
2215c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, blink::HeapHashTableBacking<Table>, void> {
2216aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    typedef typename Table::ValueType Value;
2217aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    typedef typename Table::ValueTraits Traits;
2218c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    static bool trace(blink::Visitor* visitor, void* self)
221909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
222009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        Value* array = reinterpret_cast<Value*>(self);
2221c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        blink::FinalizedHeapObjectHeader* header = blink::FinalizedHeapObjectHeader::fromPayload(self);
222209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        size_t length = header->payloadSize() / sizeof(Value);
222309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        for (size_t i = 0; i < length; i++) {
2224197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            if (!HashTableHelper<Value, typename Table::ExtractorType, typename Table::KeyTraitsType>::isEmptyOrDeletedBucket(array[i]))
2225c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                blink::CollectionBackingTraceTrait<ShouldBeTraced<Traits>::value, Traits::weakHandlingFlag, strongify, Value, Traits>::trace(visitor, array[i]);
2226323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        }
2227197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return false;
2228323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    }
2229323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)};
2230323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
22315d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)// This specialization of TraceInCollectionTrait is for the backing of
2232323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)// HeapListHashSet. This is for the case that we find a reference to the
2233323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)// backing from the stack. That probably means we have a GC while we are in a
2234323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)// ListHashSet method since normal API use does not put pointers to the backing
2235323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)// on the stack.
2236323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)template<ShouldWeakPointersBeMarkedStrongly strongify, typename NodeContents, size_t inlineCapacity, typename T, typename U, typename V, typename W, typename X, typename Y>
2237c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, blink::HeapHashTableBacking<HashTable<ListHashSetNode<NodeContents, blink::HeapListHashSetAllocator<T, inlineCapacity> >*, U, V, W, X, Y, blink::HeapAllocator> >, void> {
2238c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    typedef ListHashSetNode<NodeContents, blink::HeapListHashSetAllocator<T, inlineCapacity> > Node;
2239c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    typedef HashTable<Node*, U, V, W, X, Y, blink::HeapAllocator> Table;
2240c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    static bool trace(blink::Visitor* visitor, void* self)
2241323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    {
2242323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        Node** array = reinterpret_cast<Node**>(self);
2243c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        blink::FinalizedHeapObjectHeader* header = blink::FinalizedHeapObjectHeader::fromPayload(self);
2244323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        size_t length = header->payloadSize() / sizeof(Node*);
2245323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        for (size_t i = 0; i < length; i++) {
2246197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            if (!HashTableHelper<Node*, typename Table::ExtractorType, typename Table::KeyTraitsType>::isEmptyOrDeletedBucket(array[i])) {
2247323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)                traceListHashSetValue(visitor, array[i]->m_value);
2248323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)                // Just mark the node without tracing because we already traced
2249323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)                // the contents, and there is no need to trace the next and
2250323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)                // prev fields since iterating over the hash table backing will
2251323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)                // find the whole chain.
2252323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)                visitor->markNoTracing(array[i]);
2253323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            }
225409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
2255197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return false;
225609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
225709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
225809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
22595d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)// Key value pairs, as used in HashMap. To disambiguate template choice we have
22605d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)// to have two versions, first the one with no special weak handling, then the
22615d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)// one with weak handling.
22626f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochtemplate<ShouldWeakPointersBeMarkedStrongly strongify, typename Key, typename Value, typename Traits>
2263197021e6b966cfb06891637935ef33fff06433d1Ben Murdochstruct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, KeyValuePair<Key, Value>, Traits>  {
2264c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    static bool trace(blink::Visitor* visitor, KeyValuePair<Key, Value>& self)
226509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
2266197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        ASSERT(ShouldBeTraced<Traits>::value);
2267c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        blink::CollectionBackingTraceTrait<ShouldBeTraced<typename Traits::KeyTraits>::value, NoWeakHandlingInCollections, strongify, Key, typename Traits::KeyTraits>::trace(visitor, self.key);
2268c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        blink::CollectionBackingTraceTrait<ShouldBeTraced<typename Traits::ValueTraits>::value, NoWeakHandlingInCollections, strongify, Value, typename Traits::ValueTraits>::trace(visitor, self.value);
2269197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return false;
22706f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    }
22716f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch};
22726f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
22735d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)template<ShouldWeakPointersBeMarkedStrongly strongify, typename Key, typename Value, typename Traits>
2274197021e6b966cfb06891637935ef33fff06433d1Ben Murdochstruct TraceInCollectionTrait<WeakHandlingInCollections, strongify, KeyValuePair<Key, Value>, Traits> {
2275c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    static bool trace(blink::Visitor* visitor, KeyValuePair<Key, Value>& self)
2276197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    {
2277197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // This is the core of the ephemeron-like functionality. If there is
2278197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // weakness on the key side then we first check whether there are
2279197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // dead weak pointers on that side, and if there are we don't mark the
2280197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // value side (yet). Conversely if there is weakness on the value side
2281197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // we check that first and don't mark the key side yet if we find dead
2282197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // weak pointers.
2283197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // Corner case: If there is weakness on both the key and value side,
2284197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // and there are also strong pointers on the both sides then we could
2285197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // unexpectedly leak. The scenario is that the weak pointer on the key
2286197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // side is alive, which causes the strong pointer on the key side to be
2287197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // marked. If that then results in the object pointed to by the weak
2288197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // pointer on the value side being marked live, then the whole
2289197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // key-value entry is leaked. To avoid unexpected leaking, we disallow
2290197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // this case, but if you run into this assert, please reach out to Blink
2291197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // reviewers, and we may relax it.
2292197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        const bool keyIsWeak = Traits::KeyTraits::weakHandlingFlag == WeakHandlingInCollections;
2293197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        const bool valueIsWeak = Traits::ValueTraits::weakHandlingFlag == WeakHandlingInCollections;
2294197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        const bool keyHasStrongRefs = ShouldBeTraced<typename Traits::KeyTraits>::value;
2295197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        const bool valueHasStrongRefs = ShouldBeTraced<typename Traits::ValueTraits>::value;
2296197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        COMPILE_ASSERT(!keyIsWeak || !valueIsWeak || !keyHasStrongRefs || !valueHasStrongRefs, ThisConfigurationWasDisallowedToAvoidUnexpectedLeaks);
2297197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        if ((valueIsWeak && !keyIsWeak) || (valueIsWeak && keyIsWeak && !valueHasStrongRefs)) {
2298197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            // Check value first.
2299c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            bool deadWeakObjectsFoundOnValueSide = blink::CollectionBackingTraceTrait<ShouldBeTraced<typename Traits::ValueTraits>::value, Traits::ValueTraits::weakHandlingFlag, strongify, Value, typename Traits::ValueTraits>::trace(visitor, self.value);
2300197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            if (deadWeakObjectsFoundOnValueSide)
2301197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch                return true;
2302c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            return blink::CollectionBackingTraceTrait<ShouldBeTraced<typename Traits::KeyTraits>::value, Traits::KeyTraits::weakHandlingFlag, strongify, Key, typename Traits::KeyTraits>::trace(visitor, self.key);
2303197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        }
2304197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // Check key first.
2305c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        bool deadWeakObjectsFoundOnKeySide = blink::CollectionBackingTraceTrait<ShouldBeTraced<typename Traits::KeyTraits>::value, Traits::KeyTraits::weakHandlingFlag, strongify, Key, typename Traits::KeyTraits>::trace(visitor, self.key);
2306197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        if (deadWeakObjectsFoundOnKeySide)
2307197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            return true;
2308c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        return blink::CollectionBackingTraceTrait<ShouldBeTraced<typename Traits::ValueTraits>::value, Traits::ValueTraits::weakHandlingFlag, strongify, Value, typename Traits::ValueTraits>::trace(visitor, self.value);
230909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
231009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
231109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
23125d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)// Nodes used by LinkedHashSet. Again we need two versions to disambiguate the
23135d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)// template.
23147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccitemplate<ShouldWeakPointersBeMarkedStrongly strongify, typename Value, typename Allocator, typename Traits>
23157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccistruct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, LinkedHashSetNode<Value, Allocator>, Traits> {
23167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    static bool trace(blink::Visitor* visitor, LinkedHashSetNode<Value, Allocator>& self)
23175d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    {
2318197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        ASSERT(ShouldBeTraced<Traits>::value);
2319c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        blink::TraceTrait<Value>::trace(visitor, &self.m_value);
2320197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return false;
23215d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    }
23226f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch};
23236f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
23247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccitemplate<ShouldWeakPointersBeMarkedStrongly strongify, typename Value, typename Allocator, typename Traits>
23257242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccistruct TraceInCollectionTrait<WeakHandlingInCollections, strongify, LinkedHashSetNode<Value, Allocator>, Traits> {
23267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    static bool trace(blink::Visitor* visitor, LinkedHashSetNode<Value, Allocator>& self)
23275d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    {
2328197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return TraceInCollectionTrait<WeakHandlingInCollections, strongify, Value, typename Traits::ValueTraits>::trace(visitor, self.m_value);
23295d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    }
233009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
233109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
2332323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)// ListHashSetNode pointers (a ListHashSet is implemented as a hash table of these pointers).
2333323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)template<ShouldWeakPointersBeMarkedStrongly strongify, typename Value, size_t inlineCapacity, typename Traits>
2334c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, ListHashSetNode<Value, blink::HeapListHashSetAllocator<Value, inlineCapacity> >*, Traits> {
2335c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    typedef ListHashSetNode<Value, blink::HeapListHashSetAllocator<Value, inlineCapacity> > Node;
2336c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    static bool trace(blink::Visitor* visitor, Node* node)
2337323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    {
2338323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        traceListHashSetValue(visitor, node->m_value);
2339323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        // Just mark the node without tracing because we already traced the
2340323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        // contents, and there is no need to trace the next and prev fields
2341323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        // since iterating over the hash table backing will find the whole
2342323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        // chain.
2343323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        visitor->markNoTracing(node);
2344197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return false;
2345323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    }
2346323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)};
2347323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
2348197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch} // namespace WTF
234909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
2350c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
235109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
2352197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// CollectionBackingTraceTrait. Do nothing for things in collections that don't
2353197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// need tracing, or call TraceInCollectionTrait for those that do.
2354197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
2355197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// Specialization for things that don't need marking and have no weak pointers. We
2356197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// do nothing, even if WTF::WeakPointersActStrong.
2357197021e6b966cfb06891637935ef33fff06433d1Ben Murdochtemplate<WTF::ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits>
2358197021e6b966cfb06891637935ef33fff06433d1Ben Murdochstruct CollectionBackingTraceTrait<false, WTF::NoWeakHandlingInCollections, strongify, T, Traits> {
2359197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static bool trace(Visitor*, T&) { return false; }
23605d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)};
23615d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
2362197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// Specialization for things that either need marking or have weak pointers or
2363197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// both.
2364197021e6b966cfb06891637935ef33fff06433d1Ben Murdochtemplate<bool needsTracing, WTF::WeakHandlingFlag weakHandlingFlag, WTF::ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits>
2365197021e6b966cfb06891637935ef33fff06433d1Ben Murdochstruct CollectionBackingTraceTrait {
2366197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static bool trace(Visitor* visitor, T&t)
2367197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    {
2368197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        Visitor::verifyGarbageCollectedIfMember(reinterpret_cast<T*>(0));
2369197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return WTF::TraceInCollectionTrait<weakHandlingFlag, strongify, T, Traits>::trace(visitor, t);
2370197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
23715d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)};
23725d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
23735d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)template<typename T> struct WeakHandlingHashTraits : WTF::SimpleClassHashTraits<T> {
23745d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // We want to treat the object as a weak object in the sense that it can
23755d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // disappear from hash sets and hash maps.
23765d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    static const WTF::WeakHandlingFlag weakHandlingFlag = WTF::WeakHandlingInCollections;
23775d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // Normally whether or not an object needs tracing is inferred
23785d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // automatically from the presence of the trace method, but we don't
23795d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // necessarily have a trace method, and we may not need one because T
23805d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // can perhaps only be allocated inside collections, never as indpendent
23815d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // objects. Explicitly mark this as needing tracing and it will be traced
23825d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // in collections using the traceInCollection method, which it must have.
23835d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    template<typename U = void> struct NeedsTracingLazily {
23845d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        static const bool value = true;
23855d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    };
23865d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // The traceInCollection method traces differently depending on whether we
23875d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // are strongifying the trace operation. We strongify the trace operation
23885d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // when there are active iterators on the object. In this case all
23895d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // WeakMembers are marked like strong members so that elements do not
2390197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // suddenly disappear during iteration. Returns true if weak pointers to
2391197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // dead objects were found: In this case any strong pointers were not yet
2392197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // traced and the entry should be removed from the collection.
2393197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static bool traceInCollection(Visitor* visitor, T& t, WTF::ShouldWeakPointersBeMarkedStrongly strongify)
239409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
2395197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return t.traceInCollection(visitor, strongify);
239609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
239709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
239809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
239909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T, typename Traits>
240009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)struct TraceTrait<HeapVectorBacking<T, Traits> > {
240109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    typedef HeapVectorBacking<T, Traits> Backing;
24025d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    static void trace(Visitor* visitor, void* self)
240309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
24045d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        COMPILE_ASSERT(!WTF::IsWeak<T>::value, WeDontSupportWeaknessInHeapVectorsOrDeques);
2405d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (WTF::ShouldBeTraced<Traits>::value)
2406197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            WTF::TraceInCollectionTrait<WTF::NoWeakHandlingInCollections, WTF::WeakPointersActWeak, HeapVectorBacking<T, Traits>, void>::trace(visitor, self);
240709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
240809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static void mark(Visitor* visitor, const Backing* backing)
240909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
241009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        visitor->mark(backing, &trace);
241109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
2412d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    static void checkGCInfo(Visitor* visitor, const Backing* backing)
241309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
2414197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT)
2415d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        visitor->checkGCInfo(const_cast<Backing*>(backing), GCInfoTrait<Backing>::get());
241609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif
241709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
241809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
241909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
242009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// The trace trait for the heap hashtable backing is used when we find a
242109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// direct pointer to the backing from the conservative stack scanner. This
242209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// normally indicates that there is an ongoing iteration over the table, and so
242309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// we disable weak processing of table entries. When the backing is found
242409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// through the owning hash table we mark differently, in order to do weak
242509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// processing.
2426aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdochtemplate<typename Table>
2427aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdochstruct TraceTrait<HeapHashTableBacking<Table> > {
2428aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    typedef HeapHashTableBacking<Table> Backing;
2429aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    typedef typename Table::ValueTraits Traits;
24305d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    static void trace(Visitor* visitor, void* self)
243109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
24325d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        if (WTF::ShouldBeTraced<Traits>::value || Traits::weakHandlingFlag == WTF::WeakHandlingInCollections)
2433197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            WTF::TraceInCollectionTrait<WTF::NoWeakHandlingInCollections, WTF::WeakPointersActStrong, Backing, void>::trace(visitor, self);
243409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
243509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static void mark(Visitor* visitor, const Backing* backing)
243609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
24375d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        if (WTF::ShouldBeTraced<Traits>::value || Traits::weakHandlingFlag == WTF::WeakHandlingInCollections)
243809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            visitor->mark(backing, &trace);
243909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        else
2440323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            visitor->markNoTracing(backing); // If we know the trace function will do nothing there is no need to call it.
244109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
2442d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    static void checkGCInfo(Visitor* visitor, const Backing* backing)
244309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    {
2444197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT)
2445d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        visitor->checkGCInfo(const_cast<Backing*>(backing), GCInfoTrait<Backing>::get());
244609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif
244709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
244809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
244909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
2450aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdochtemplate<typename Table>
2451aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdochvoid HeapHashTableBacking<Table>::finalize(void* pointer)
2452aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch{
2453aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    typedef typename Table::ValueType Value;
2454aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    ASSERT(Table::ValueTraits::needsDestruction);
2455aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    FinalizedHeapObjectHeader* header = FinalizedHeapObjectHeader::fromPayload(pointer);
2456aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    // Use the payload size as recorded by the heap to determine how many
2457aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    // elements to finalize.
2458aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    size_t length = header->payloadSize() / sizeof(Value);
2459aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    Value* table = reinterpret_cast<Value*>(pointer);
2460aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    for (unsigned i = 0; i < length; i++) {
2461aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch        if (!Table::isEmptyOrDeletedBucket(table[i]))
2462aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch            table[i].~Value();
2463aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    }
2464aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch}
2465aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch
246609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T, typename U, typename V, typename W, typename X>
246709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)struct GCInfoTrait<HeapHashMap<T, U, V, W, X> > : public GCInfoTrait<HashMap<T, U, V, W, X, HeapAllocator> > { };
246809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T, typename U, typename V>
246909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)struct GCInfoTrait<HeapHashSet<T, U, V> > : public GCInfoTrait<HashSet<T, U, V, HeapAllocator> > { };
24706f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochtemplate<typename T, typename U, typename V>
24716f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochstruct GCInfoTrait<HeapLinkedHashSet<T, U, V> > : public GCInfoTrait<LinkedHashSet<T, U, V, HeapAllocator> > { };
2472323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)template<typename T, size_t inlineCapacity, typename U>
2473323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)struct GCInfoTrait<HeapListHashSet<T, inlineCapacity, U> > : public GCInfoTrait<ListHashSet<T, inlineCapacity, U, HeapListHashSetAllocator<T, inlineCapacity> > > { };
247409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T, size_t inlineCapacity>
247509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)struct GCInfoTrait<HeapVector<T, inlineCapacity> > : public GCInfoTrait<Vector<T, inlineCapacity, HeapAllocator> > { };
2476a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochtemplate<typename T, size_t inlineCapacity>
2477a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct GCInfoTrait<HeapDeque<T, inlineCapacity> > : public GCInfoTrait<Deque<T, inlineCapacity, HeapAllocator> > { };
2478f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liutemplate<typename T, typename U, typename V>
2479f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liustruct GCInfoTrait<HeapHashCountedSet<T, U, V> > : public GCInfoTrait<HashCountedSet<T, U, V, HeapAllocator> > { };
248009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
248109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T>
248209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)struct IfWeakMember;
248309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
248409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T>
248509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)struct IfWeakMember {
248609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    template<typename U>
248709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static bool isDead(Visitor*, const U&) { return false; }
248809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
248909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
249009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename T>
249109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)struct IfWeakMember<WeakMember<T> > {
249209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static bool isDead(Visitor* visitor, const WeakMember<T>& t) { return !visitor->isAlive(t.get()); }
249309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
249409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
2495a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)}
24965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2497a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#endif // Heap_h
2498