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