1 /* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #ifndef Heap_h 32 #define Heap_h 33 34 #include "platform/PlatformExport.h" 35 #include "platform/heap/AddressSanitizer.h" 36 #include "platform/heap/ThreadState.h" 37 #include "platform/heap/Visitor.h" 38 39 #include "wtf/Assertions.h" 40 #include "wtf/HashCountedSet.h" 41 #include "wtf/LinkedHashSet.h" 42 #include "wtf/ListHashSet.h" 43 #include "wtf/OwnPtr.h" 44 #include "wtf/PassRefPtr.h" 45 #include "wtf/ThreadSafeRefCounted.h" 46 47 #include <stdint.h> 48 49 namespace WebCore { 50 51 const size_t blinkPageSizeLog2 = 17; 52 const size_t blinkPageSize = 1 << blinkPageSizeLog2; 53 const size_t blinkPageOffsetMask = blinkPageSize - 1; 54 const size_t blinkPageBaseMask = ~blinkPageOffsetMask; 55 // Double precision floats are more efficient when 8 byte aligned, so we 8 byte 56 // align all allocations even on 32 bit. 57 const size_t allocationGranularity = 8; 58 const size_t allocationMask = allocationGranularity - 1; 59 const size_t objectStartBitMapSize = (blinkPageSize + ((8 * allocationGranularity) - 1)) / (8 * allocationGranularity); 60 const size_t reservedForObjectBitMap = ((objectStartBitMapSize + allocationMask) & ~allocationMask); 61 const size_t maxHeapObjectSize = 1 << 27; 62 63 const size_t markBitMask = 1; 64 const size_t freeListMask = 2; 65 const size_t debugBitMask = 4; 66 const size_t sizeMask = ~7; 67 const uint8_t freelistZapValue = 42; 68 const uint8_t finalizedZapValue = 24; 69 70 class HeapStats; 71 class PageMemory; 72 template<ThreadAffinity affinity> class ThreadLocalPersistents; 73 template<typename T, typename RootsAccessor = ThreadLocalPersistents<ThreadingTrait<T>::Affinity > > class Persistent; 74 template<typename T> class CrossThreadPersistent; 75 76 PLATFORM_EXPORT size_t osPageSize(); 77 78 // Blink heap pages are set up with a guard page before and after the 79 // payload. 80 inline size_t blinkPagePayloadSize() 81 { 82 return blinkPageSize - 2 * osPageSize(); 83 } 84 85 // Blink heap pages are aligned to the Blink heap page size. 86 // Therefore, the start of a Blink page can be obtained by 87 // rounding down to the Blink page size. 88 inline Address roundToBlinkPageStart(Address address) 89 { 90 return reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address) & blinkPageBaseMask); 91 } 92 93 inline Address roundToBlinkPageEnd(Address address) 94 { 95 return reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address - 1) & blinkPageBaseMask) + blinkPageSize; 96 } 97 98 // Compute the amount of padding we have to add to a header to make 99 // the size of the header plus the padding a multiple of 8 bytes. 100 template<typename Header> 101 inline size_t headerPadding() 102 { 103 return (allocationGranularity - (sizeof(Header) % allocationGranularity)) % allocationGranularity; 104 } 105 106 // Masks an address down to the enclosing blink page base address. 107 inline Address blinkPageAddress(Address address) 108 { 109 return reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address) & blinkPageBaseMask); 110 } 111 112 #ifndef NDEBUG 113 114 // Sanity check for a page header address: the address of the page 115 // header should be OS page size away from being Blink page size 116 // aligned. 117 inline bool isPageHeaderAddress(Address address) 118 { 119 return !((reinterpret_cast<uintptr_t>(address) & blinkPageOffsetMask) - osPageSize()); 120 } 121 #endif 122 123 // Mask an address down to the enclosing oilpan heap page base address. 124 // All oilpan heap pages are aligned at blinkPageBase plus an OS page size. 125 // FIXME: Remove PLATFORM_EXPORT once we get a proper public interface to our typed heaps. 126 // This is only exported to enable tests in HeapTest.cpp. 127 PLATFORM_EXPORT inline Address pageHeaderAddress(Address address) 128 { 129 return blinkPageAddress(address) + osPageSize(); 130 } 131 132 // Common header for heap pages. 133 class BaseHeapPage { 134 public: 135 BaseHeapPage(PageMemory* storage, const GCInfo* gcInfo, ThreadState* state) 136 : m_storage(storage) 137 , m_gcInfo(gcInfo) 138 , m_threadState(state) 139 , m_padding(0) 140 { 141 ASSERT(isPageHeaderAddress(reinterpret_cast<Address>(this))); 142 } 143 144 // Check if the given address points to an object in this 145 // heap page. If so, find the start of that object and mark it 146 // using the given Visitor. Otherwise do nothing. The pointer must 147 // be within the same aligned blinkPageSize as the this-pointer. 148 // 149 // This is used during conservative stack scanning to 150 // conservatively mark all objects that could be referenced from 151 // the stack. 152 virtual void checkAndMarkPointer(Visitor*, Address) = 0; 153 154 #if ENABLE(GC_TRACING) 155 virtual const GCInfo* findGCInfo(Address) = 0; 156 #endif 157 158 Address address() { return reinterpret_cast<Address>(this); } 159 PageMemory* storage() const { return m_storage; } 160 ThreadState* threadState() const { return m_threadState; } 161 const GCInfo* gcInfo() { return m_gcInfo; } 162 virtual bool isLargeObject() { return false; } 163 164 private: 165 // Accessor to silence unused warnings for the m_padding field. 166 intptr_t padding() const { return m_padding; } 167 168 PageMemory* m_storage; 169 const GCInfo* m_gcInfo; 170 ThreadState* m_threadState; 171 // Pointer sized integer to ensure proper alignment of the 172 // HeapPage header. This can be used as a bit field if we need 173 // to associate more information with pages. 174 intptr_t m_padding; 175 }; 176 177 // Large allocations are allocated as separate objects and linked in a 178 // list. 179 // 180 // In order to use the same memory allocation routines for everything 181 // allocated in the heap, large objects are considered heap pages 182 // containing only one object. 183 // 184 // The layout of a large heap object is as follows: 185 // 186 // | BaseHeapPage | next pointer | FinalizedHeapObjectHeader or HeapObjectHeader | payload | 187 template<typename Header> 188 class LargeHeapObject : public BaseHeapPage { 189 public: 190 LargeHeapObject(PageMemory* storage, const GCInfo* gcInfo, ThreadState* state) : BaseHeapPage(storage, gcInfo, state) 191 { 192 COMPILE_ASSERT(!(sizeof(LargeHeapObject<Header>) & allocationMask), large_heap_object_header_misaligned); 193 } 194 195 virtual void checkAndMarkPointer(Visitor*, Address) OVERRIDE; 196 virtual bool isLargeObject() OVERRIDE { return true; } 197 198 #if ENABLE(GC_TRACING) 199 virtual const GCInfo* findGCInfo(Address address) 200 { 201 if (!objectContains(address)) 202 return 0; 203 return gcInfo(); 204 } 205 #endif 206 207 void link(LargeHeapObject<Header>** previousNext) 208 { 209 m_next = *previousNext; 210 *previousNext = this; 211 } 212 213 void unlink(LargeHeapObject<Header>** previousNext) 214 { 215 *previousNext = m_next; 216 } 217 218 // The LargeHeapObject pseudo-page contains one actual object. Determine 219 // whether the pointer is within that object. 220 bool objectContains(Address object) 221 { 222 return (payload() <= object) && (object < address() + size()); 223 } 224 225 // Returns true for any address that is on one of the pages that this 226 // large object uses. That ensures that we can use a negative result to 227 // populate the negative page cache. 228 bool contains(Address object) 229 { 230 return roundToBlinkPageStart(address()) <= object && object < roundToBlinkPageEnd(address() + size()); 231 } 232 233 LargeHeapObject<Header>* next() 234 { 235 return m_next; 236 } 237 238 size_t size() 239 { 240 return heapObjectHeader()->size() + sizeof(LargeHeapObject<Header>) + headerPadding<Header>(); 241 } 242 243 Address payload() { return heapObjectHeader()->payload(); } 244 size_t payloadSize() { return heapObjectHeader()->payloadSize(); } 245 246 Header* heapObjectHeader() 247 { 248 Address headerAddress = address() + sizeof(LargeHeapObject<Header>) + headerPadding<Header>(); 249 return reinterpret_cast<Header*>(headerAddress); 250 } 251 252 bool isMarked(); 253 void unmark(); 254 void getStats(HeapStats&); 255 void mark(Visitor*); 256 void finalize(); 257 258 private: 259 friend class ThreadHeap<Header>; 260 261 LargeHeapObject<Header>* m_next; 262 }; 263 264 // The BasicObjectHeader is the minimal object header. It is used when 265 // encountering heap space of size allocationGranularity to mark it as 266 // as freelist entry. 267 class PLATFORM_EXPORT BasicObjectHeader { 268 public: 269 NO_SANITIZE_ADDRESS 270 explicit BasicObjectHeader(size_t encodedSize) 271 : m_size(encodedSize) { } 272 273 static size_t freeListEncodedSize(size_t size) { return size | freeListMask; } 274 275 NO_SANITIZE_ADDRESS 276 bool isFree() { return m_size & freeListMask; } 277 278 NO_SANITIZE_ADDRESS 279 size_t size() const { return m_size & sizeMask; } 280 281 protected: 282 size_t m_size; 283 }; 284 285 // Our heap object layout is layered with the HeapObjectHeader closest 286 // to the payload, this can be wrapped in a FinalizedObjectHeader if the 287 // object is on the GeneralHeap and not on a specific TypedHeap. 288 // Finally if the object is a large object (> blinkPageSize/2) then it is 289 // wrapped with a LargeObjectHeader. 290 // 291 // Object memory layout: 292 // [ LargeObjectHeader | ] [ FinalizedObjectHeader | ] HeapObjectHeader | payload 293 // The [ ] notation denotes that the LargeObjectHeader and the FinalizedObjectHeader 294 // are independently optional. 295 class PLATFORM_EXPORT HeapObjectHeader : public BasicObjectHeader { 296 public: 297 NO_SANITIZE_ADDRESS 298 explicit HeapObjectHeader(size_t encodedSize) 299 : BasicObjectHeader(encodedSize) 300 #ifndef NDEBUG 301 , m_magic(magic) 302 #endif 303 { } 304 305 NO_SANITIZE_ADDRESS 306 HeapObjectHeader(size_t encodedSize, const GCInfo*) 307 : BasicObjectHeader(encodedSize) 308 #ifndef NDEBUG 309 , m_magic(magic) 310 #endif 311 { } 312 313 inline void checkHeader() const; 314 inline bool isMarked() const; 315 316 inline void mark(); 317 inline void unmark(); 318 319 inline const GCInfo* gcInfo() { return 0; } 320 321 inline Address payload(); 322 inline size_t payloadSize(); 323 inline Address payloadEnd(); 324 325 inline void setDebugMark(); 326 inline void clearDebugMark(); 327 inline bool hasDebugMark() const; 328 329 // Zap magic number with a new magic number that means there was once an 330 // object allocated here, but it was freed because nobody marked it during 331 // GC. 332 void zapMagic(); 333 334 static void finalize(const GCInfo*, Address, size_t); 335 static HeapObjectHeader* fromPayload(const void*); 336 337 static const intptr_t magic = 0xc0de247; 338 static const intptr_t zappedMagic = 0xC0DEdead; 339 // The zap value for vtables should be < 4K to ensure it cannot be 340 // used for dispatch. 341 static const intptr_t zappedVTable = 0xd0d; 342 343 private: 344 #ifndef NDEBUG 345 intptr_t m_magic; 346 #endif 347 }; 348 349 const size_t objectHeaderSize = sizeof(HeapObjectHeader); 350 351 // Each object on the GeneralHeap needs to carry a pointer to its 352 // own GCInfo structure for tracing and potential finalization. 353 class PLATFORM_EXPORT FinalizedHeapObjectHeader : public HeapObjectHeader { 354 public: 355 NO_SANITIZE_ADDRESS 356 FinalizedHeapObjectHeader(size_t encodedSize, const GCInfo* gcInfo) 357 : HeapObjectHeader(encodedSize) 358 , m_gcInfo(gcInfo) 359 { 360 } 361 362 inline Address payload(); 363 inline size_t payloadSize(); 364 365 NO_SANITIZE_ADDRESS 366 const GCInfo* gcInfo() { return m_gcInfo; } 367 368 NO_SANITIZE_ADDRESS 369 TraceCallback traceCallback() { return m_gcInfo->m_trace; } 370 371 void finalize(); 372 373 NO_SANITIZE_ADDRESS 374 inline bool hasFinalizer() { return m_gcInfo->hasFinalizer(); } 375 376 static FinalizedHeapObjectHeader* fromPayload(const void*); 377 378 NO_SANITIZE_ADDRESS 379 bool hasVTable() { return m_gcInfo->hasVTable(); } 380 381 private: 382 const GCInfo* m_gcInfo; 383 }; 384 385 const size_t finalizedHeaderSize = sizeof(FinalizedHeapObjectHeader); 386 387 class FreeListEntry : public HeapObjectHeader { 388 public: 389 NO_SANITIZE_ADDRESS 390 explicit FreeListEntry(size_t size) 391 : HeapObjectHeader(freeListEncodedSize(size)) 392 , m_next(0) 393 { 394 #if !defined(NDEBUG) && !ASAN 395 // Zap free area with asterisks, aka 0x2a2a2a2a. 396 // For ASAN don't zap since we keep accounting in the freelist entry. 397 for (size_t i = sizeof(*this); i < size; i++) 398 reinterpret_cast<Address>(this)[i] = freelistZapValue; 399 ASSERT(size >= objectHeaderSize); 400 zapMagic(); 401 #endif 402 } 403 404 Address address() { return reinterpret_cast<Address>(this); } 405 406 NO_SANITIZE_ADDRESS 407 void unlink(FreeListEntry** prevNext) 408 { 409 *prevNext = m_next; 410 m_next = 0; 411 } 412 413 NO_SANITIZE_ADDRESS 414 void link(FreeListEntry** prevNext) 415 { 416 m_next = *prevNext; 417 *prevNext = this; 418 } 419 420 #if defined(ADDRESS_SANITIZER) 421 NO_SANITIZE_ADDRESS 422 bool shouldAddToFreeList() 423 { 424 // Init if not already magic. 425 if ((m_asanMagic & ~asanDeferMemoryReuseMask) != asanMagic) { 426 m_asanMagic = asanMagic | asanDeferMemoryReuseCount; 427 return false; 428 } 429 // Decrement if count part of asanMagic > 0. 430 if (m_asanMagic & asanDeferMemoryReuseMask) 431 m_asanMagic--; 432 return !(m_asanMagic & asanDeferMemoryReuseMask); 433 } 434 #endif 435 436 private: 437 FreeListEntry* m_next; 438 #if defined(ADDRESS_SANITIZER) 439 unsigned m_asanMagic; 440 #endif 441 }; 442 443 // Representation of Blink heap pages. 444 // 445 // Pages are specialized on the type of header on the object they 446 // contain. If a heap page only contains a certain type of object all 447 // of the objects will have the same GCInfo pointer and therefore that 448 // pointer can be stored in the HeapPage instead of in the header of 449 // each object. In that case objects have only a HeapObjectHeader and 450 // not a FinalizedHeapObjectHeader saving a word per object. 451 template<typename Header> 452 class HeapPage : public BaseHeapPage { 453 public: 454 HeapPage(PageMemory*, ThreadHeap<Header>*, const GCInfo*); 455 456 void link(HeapPage**); 457 static void unlink(HeapPage*, HeapPage**); 458 459 bool isEmpty(); 460 461 // Returns true for the whole blinkPageSize page that the page is on, even 462 // for the header, and the unmapped guard page at the start. That ensures 463 // the result can be used to populate the negative page cache. 464 bool contains(Address addr) 465 { 466 Address blinkPageStart = roundToBlinkPageStart(address()); 467 ASSERT(blinkPageStart == address() - osPageSize()); // Page is at aligned address plus guard page size. 468 return blinkPageStart <= addr && addr < blinkPageStart + blinkPageSize; 469 } 470 471 HeapPage* next() { return m_next; } 472 473 Address payload() 474 { 475 return address() + sizeof(*this) + headerPadding<Header>(); 476 } 477 478 static size_t payloadSize() 479 { 480 return (blinkPagePayloadSize() - sizeof(HeapPage) - headerPadding<Header>()) & ~allocationMask; 481 } 482 483 Address end() { return payload() + payloadSize(); } 484 485 void getStats(HeapStats&); 486 void clearMarks(); 487 void sweep(); 488 void clearObjectStartBitMap(); 489 void finalize(Header*); 490 virtual void checkAndMarkPointer(Visitor*, Address) OVERRIDE; 491 #if ENABLE(GC_TRACING) 492 const GCInfo* findGCInfo(Address) OVERRIDE; 493 #endif 494 ThreadHeap<Header>* heap() { return m_heap; } 495 #if defined(ADDRESS_SANITIZER) 496 void poisonUnmarkedObjects(); 497 #endif 498 499 protected: 500 Header* findHeaderFromAddress(Address); 501 void populateObjectStartBitMap(); 502 bool isObjectStartBitMapComputed() { return m_objectStartBitMapComputed; } 503 TraceCallback traceCallback(Header*); 504 bool hasVTable(Header*); 505 506 HeapPage<Header>* m_next; 507 ThreadHeap<Header>* m_heap; 508 bool m_objectStartBitMapComputed; 509 uint8_t m_objectStartBitMap[reservedForObjectBitMap]; 510 511 friend class ThreadHeap<Header>; 512 }; 513 514 class AddressEntry { 515 public: 516 AddressEntry() : m_address(0) { } 517 518 explicit AddressEntry(Address address) : m_address(address) { } 519 520 Address address() const { return m_address; } 521 522 private: 523 Address m_address; 524 }; 525 526 class PositiveEntry : public AddressEntry { 527 public: 528 PositiveEntry() 529 : AddressEntry() 530 , m_containingPage(0) 531 { 532 } 533 534 PositiveEntry(Address address, BaseHeapPage* containingPage) 535 : AddressEntry(address) 536 , m_containingPage(containingPage) 537 { 538 } 539 540 BaseHeapPage* result() const { return m_containingPage; } 541 542 typedef BaseHeapPage* LookupResult; 543 544 private: 545 BaseHeapPage* m_containingPage; 546 }; 547 548 class NegativeEntry : public AddressEntry { 549 public: 550 NegativeEntry() : AddressEntry() { } 551 552 NegativeEntry(Address address, bool) : AddressEntry(address) { } 553 554 bool result() const { return true; } 555 556 typedef bool LookupResult; 557 }; 558 559 // A HeapExtentCache provides a fast way of taking an arbitrary 560 // pointer-sized word, and determining whether it can be interpreted 561 // as a pointer to an area that is managed by the garbage collected 562 // Blink heap. There is a cache of 'pages' that have previously been 563 // determined to be wholly inside the heap. The size of these pages must be 564 // smaller than the allocation alignment of the heap pages. We determine 565 // on-heap-ness by rounding down the pointer to the nearest page and looking up 566 // the page in the cache. If there is a miss in the cache we can ask the heap 567 // to determine the status of the pointer by iterating over all of the heap. 568 // The result is then cached in the two-way associative page cache. 569 // 570 // A HeapContainsCache is a positive cache. Therefore, it must be flushed when 571 // memory is removed from the Blink heap. The HeapDoesNotContainCache is a 572 // negative cache, so it must be flushed when memory is added to the heap. 573 template<typename Entry> 574 class HeapExtentCache { 575 public: 576 HeapExtentCache() 577 : m_entries(adoptArrayPtr(new Entry[HeapExtentCache::numberOfEntries])) 578 , m_hasEntries(false) 579 { 580 } 581 582 void flush(); 583 bool contains(Address); 584 bool isEmpty() { return !m_hasEntries; } 585 586 // Perform a lookup in the cache. 587 // 588 // If lookup returns null/false the argument address was not found in 589 // the cache and it is unknown if the address is in the Blink 590 // heap. 591 // 592 // If lookup returns true/a page, the argument address was found in the 593 // cache. For the HeapContainsCache this means the address is in the heap. 594 // For the HeapDoesNotContainCache this means the address is not in the 595 // heap. 596 PLATFORM_EXPORT typename Entry::LookupResult lookup(Address); 597 598 // Add an entry to the cache. 599 PLATFORM_EXPORT void addEntry(Address, typename Entry::LookupResult); 600 601 private: 602 static const int numberOfEntriesLog2 = 12; 603 static const int numberOfEntries = 1 << numberOfEntriesLog2; 604 605 static size_t hash(Address); 606 607 WTF::OwnPtr<Entry[]> m_entries; 608 bool m_hasEntries; 609 610 friend class ThreadState; 611 }; 612 613 // Normally these would be typedefs instead of subclasses, but that makes them 614 // very hard to forward declare. 615 class HeapContainsCache : public HeapExtentCache<PositiveEntry> { 616 public: 617 BaseHeapPage* lookup(Address); 618 void addEntry(Address, BaseHeapPage*); 619 }; 620 621 class HeapDoesNotContainCache : public HeapExtentCache<NegativeEntry> { }; 622 623 // FIXME: This is currently used by the WebAudio code. 624 // We should attempt to restructure the WebAudio code so that the main thread 625 // alone determines life-time and receives messages about life-time from the 626 // audio thread. 627 template<typename T> 628 class ThreadSafeRefCountedGarbageCollected : public GarbageCollectedFinalized<T>, public WTF::ThreadSafeRefCountedBase { 629 WTF_MAKE_NONCOPYABLE(ThreadSafeRefCountedGarbageCollected); 630 631 public: 632 ThreadSafeRefCountedGarbageCollected() 633 { 634 m_keepAlive = adoptPtr(new CrossThreadPersistent<T>(static_cast<T*>(this))); 635 } 636 637 // Override ref to deal with a case where a reference count goes up 638 // from 0 to 1. This can happen in the following scenario: 639 // (1) The reference count becomes 0, but on-stack pointers keep references to the object. 640 // (2) The on-stack pointer is assigned to a RefPtr. The reference count becomes 1. 641 // In this case, we have to resurrect m_keepAlive. 642 void ref() 643 { 644 MutexLocker lock(m_mutex); 645 if (UNLIKELY(!refCount())) { 646 ASSERT(!m_keepAlive); 647 m_keepAlive = adoptPtr(new CrossThreadPersistent<T>(static_cast<T*>(this))); 648 } 649 WTF::ThreadSafeRefCountedBase::ref(); 650 } 651 652 // Override deref to deal with our own deallocation based on ref counting. 653 void deref() 654 { 655 MutexLocker lock(m_mutex); 656 if (derefBase()) { 657 ASSERT(m_keepAlive); 658 m_keepAlive.clear(); 659 } 660 } 661 662 using GarbageCollectedFinalized<T>::operator new; 663 using GarbageCollectedFinalized<T>::operator delete; 664 665 protected: 666 ~ThreadSafeRefCountedGarbageCollected() { } 667 668 private: 669 OwnPtr<CrossThreadPersistent<T> > m_keepAlive; 670 mutable Mutex m_mutex; 671 }; 672 673 // The CallbackStack contains all the visitor callbacks used to trace and mark 674 // objects. A specific CallbackStack instance contains at most bufferSize elements. 675 // If more space is needed a new CallbackStack instance is created and chained 676 // together with the former instance. I.e. a logical CallbackStack can be made of 677 // multiple chained CallbackStack object instances. 678 // There are two logical callback stacks. One containing all the marking callbacks and 679 // one containing the weak pointer callbacks. 680 class CallbackStack { 681 public: 682 CallbackStack(CallbackStack** first) 683 : m_limit(&(m_buffer[bufferSize])) 684 , m_current(&(m_buffer[0])) 685 , m_next(*first) 686 { 687 #ifndef NDEBUG 688 clearUnused(); 689 #endif 690 *first = this; 691 } 692 693 ~CallbackStack(); 694 void clearUnused(); 695 696 void assertIsEmpty(); 697 698 class Item { 699 public: 700 Item() { } 701 Item(void* object, VisitorCallback callback) 702 : m_object(object) 703 , m_callback(callback) 704 { 705 } 706 void* object() { return m_object; } 707 VisitorCallback callback() { return m_callback; } 708 709 private: 710 void* m_object; 711 VisitorCallback m_callback; 712 }; 713 714 static void init(CallbackStack** first); 715 static void shutdown(CallbackStack** first); 716 bool popAndInvokeCallback(CallbackStack** first, Visitor*); 717 718 Item* allocateEntry(CallbackStack** first) 719 { 720 if (m_current < m_limit) 721 return m_current++; 722 return (new CallbackStack(first))->allocateEntry(first); 723 } 724 725 private: 726 static const size_t bufferSize = 8000; 727 Item m_buffer[bufferSize]; 728 Item* m_limit; 729 Item* m_current; 730 CallbackStack* m_next; 731 }; 732 733 // Non-template super class used to pass a heap around to other classes. 734 class BaseHeap { 735 public: 736 virtual ~BaseHeap() { } 737 738 // Find the page in this thread heap containing the given 739 // address. Returns 0 if the address is not contained in any 740 // page in this thread heap. 741 virtual BaseHeapPage* heapPageFromAddress(Address) = 0; 742 743 #if ENABLE(GC_TRACING) 744 virtual const GCInfo* findGCInfoOfLargeHeapObject(Address) = 0; 745 #endif 746 747 // Sweep this part of the Blink heap. This finalizes dead objects 748 // and builds freelists for all the unused memory. 749 virtual void sweep() = 0; 750 751 // Forcefully finalize all objects in this part of the Blink heap 752 // (potentially with the exception of one object). This is used 753 // during thread termination to make sure that all objects for the 754 // dying thread are finalized. 755 virtual void assertEmpty() = 0; 756 757 virtual void clearFreeLists() = 0; 758 virtual void clearMarks() = 0; 759 #ifndef NDEBUG 760 virtual void getScannedStats(HeapStats&) = 0; 761 #endif 762 763 virtual void makeConsistentForGC() = 0; 764 virtual bool isConsistentForGC() = 0; 765 766 // Returns a bucket number for inserting a FreeListEntry of a 767 // given size. All FreeListEntries in the given bucket, n, have 768 // size >= 2^n. 769 static int bucketIndexForSize(size_t); 770 }; 771 772 // Thread heaps represent a part of the per-thread Blink heap. 773 // 774 // Each Blink thread has a number of thread heaps: one general heap 775 // that contains any type of object and a number of heaps specialized 776 // for specific object types (such as Node). 777 // 778 // Each thread heap contains the functionality to allocate new objects 779 // (potentially adding new pages to the heap), to find and mark 780 // objects during conservative stack scanning and to sweep the set of 781 // pages after a GC. 782 template<typename Header> 783 class ThreadHeap : public BaseHeap { 784 public: 785 ThreadHeap(ThreadState*); 786 virtual ~ThreadHeap(); 787 788 virtual BaseHeapPage* heapPageFromAddress(Address); 789 #if ENABLE(GC_TRACING) 790 virtual const GCInfo* findGCInfoOfLargeHeapObject(Address); 791 #endif 792 virtual void sweep(); 793 virtual void assertEmpty(); 794 virtual void clearFreeLists(); 795 virtual void clearMarks(); 796 #ifndef NDEBUG 797 virtual void getScannedStats(HeapStats&); 798 #endif 799 800 virtual void makeConsistentForGC(); 801 virtual bool isConsistentForGC(); 802 803 ThreadState* threadState() { return m_threadState; } 804 HeapStats& stats() { return m_threadState->stats(); } 805 void flushHeapContainsCache() 806 { 807 m_threadState->heapContainsCache()->flush(); 808 } 809 810 inline Address allocate(size_t, const GCInfo*); 811 void addToFreeList(Address, size_t); 812 void addPageToPool(HeapPage<Header>*); 813 inline static size_t roundedAllocationSize(size_t size) 814 { 815 return allocationSizeFromSize(size) - sizeof(Header); 816 } 817 818 private: 819 // Once pages have been used for one thread heap they will never 820 // be reused for another thread heap. Instead of unmapping, we add 821 // the pages to a pool of pages to be reused later by this thread 822 // heap. This is done as a security feature to avoid type 823 // confusion. The heap is type segregated by having separate 824 // thread heaps for various types of objects. Holding on to pages 825 // ensures that the same virtual address space cannot be used for 826 // objects of another type than the type contained in this thread 827 // heap. 828 class PagePoolEntry { 829 public: 830 PagePoolEntry(PageMemory* storage, PagePoolEntry* next) 831 : m_storage(storage) 832 , m_next(next) 833 { } 834 835 PageMemory* storage() { return m_storage; } 836 PagePoolEntry* next() { return m_next; } 837 838 private: 839 PageMemory* m_storage; 840 PagePoolEntry* m_next; 841 }; 842 843 PLATFORM_EXPORT Address outOfLineAllocate(size_t, const GCInfo*); 844 static size_t allocationSizeFromSize(size_t); 845 void addPageToHeap(const GCInfo*); 846 PLATFORM_EXPORT Address allocateLargeObject(size_t, const GCInfo*); 847 Address currentAllocationPoint() const { return m_currentAllocationPoint; } 848 size_t remainingAllocationSize() const { return m_remainingAllocationSize; } 849 bool ownsNonEmptyAllocationArea() const { return currentAllocationPoint() && remainingAllocationSize(); } 850 void setAllocationPoint(Address point, size_t size) 851 { 852 ASSERT(!point || heapPageFromAddress(point)); 853 ASSERT(size <= HeapPage<Header>::payloadSize()); 854 m_currentAllocationPoint = point; 855 m_remainingAllocationSize = size; 856 } 857 void ensureCurrentAllocation(size_t, const GCInfo*); 858 bool allocateFromFreeList(size_t); 859 860 void freeLargeObject(LargeHeapObject<Header>*, LargeHeapObject<Header>**); 861 862 void allocatePage(const GCInfo*); 863 PageMemory* takePageFromPool(); 864 void clearPagePool(); 865 void deletePages(); 866 867 Address m_currentAllocationPoint; 868 size_t m_remainingAllocationSize; 869 870 HeapPage<Header>* m_firstPage; 871 LargeHeapObject<Header>* m_firstLargeHeapObject; 872 873 int m_biggestFreeListIndex; 874 ThreadState* m_threadState; 875 876 // All FreeListEntries in the nth list have size >= 2^n. 877 FreeListEntry* m_freeLists[blinkPageSizeLog2]; 878 879 // List of pages that have been previously allocated, but are now 880 // unused. 881 PagePoolEntry* m_pagePool; 882 }; 883 884 class PLATFORM_EXPORT Heap { 885 public: 886 static void init(); 887 static void shutdown(); 888 static void doShutdown(); 889 890 static BaseHeapPage* contains(Address); 891 static BaseHeapPage* contains(void* pointer) { return contains(reinterpret_cast<Address>(pointer)); } 892 static BaseHeapPage* contains(const void* pointer) { return contains(const_cast<void*>(pointer)); } 893 894 // Push a trace callback on the marking stack. 895 static void pushTraceCallback(void* containerObject, TraceCallback); 896 897 // Add a weak pointer callback to the weak callback work list. General 898 // object pointer callbacks are added to a thread local weak callback work 899 // list and the callback is called on the thread that owns the object, with 900 // the closure pointer as an argument. Most of the time, the closure and 901 // the containerObject can be the same thing, but the containerObject is 902 // constrained to be on the heap, since the heap is used to identify the 903 // correct thread. 904 static void pushWeakObjectPointerCallback(void* closure, void* containerObject, WeakPointerCallback); 905 906 // Similar to the more general pushWeakObjectPointerCallback, but cell 907 // pointer callbacks are added to a static callback work list and the weak 908 // callback is performed on the thread performing garbage collection. This 909 // is OK because cells are just cleared and no deallocation can happen. 910 static void pushWeakCellPointerCallback(void** cell, WeakPointerCallback); 911 912 // Pop the top of the marking stack and call the callback with the visitor 913 // and the object. Returns false when there is nothing more to do. 914 static bool popAndInvokeTraceCallback(Visitor*); 915 916 // Remove an item from the weak callback work list and call the callback 917 // with the visitor and the closure pointer. Returns false when there is 918 // nothing more to do. 919 static bool popAndInvokeWeakPointerCallback(Visitor*); 920 921 template<typename T> static Address allocate(size_t); 922 template<typename T> static Address reallocate(void* previous, size_t); 923 924 static void collectGarbage(ThreadState::StackState); 925 static void collectAllGarbage(); 926 static void setForcePreciseGCForTesting(); 927 928 static void prepareForGC(); 929 930 // Conservatively checks whether an address is a pointer in any of the thread 931 // heaps. If so marks the object pointed to as live. 932 static Address checkAndMarkPointer(Visitor*, Address); 933 934 #if ENABLE(GC_TRACING) 935 // Dump the path to specified object on the next GC. This method is to be invoked from GDB. 936 static void dumpPathToObjectOnNextGC(void* p); 937 938 // Forcibly find GCInfo of the object at Address. 939 // This is slow and should only be used for debug purposes. 940 // It involves finding the heap page and scanning the heap page for an object header. 941 static const GCInfo* findGCInfo(Address); 942 943 static String createBacktraceString(); 944 #endif 945 946 // Collect heap stats for all threads attached to the Blink 947 // garbage collector. Should only be called during garbage 948 // collection where threads are known to be at safe points. 949 static void getStats(HeapStats*); 950 951 static void getHeapSpaceSize(uint64_t*, uint64_t*); 952 953 static bool isConsistentForGC(); 954 static void makeConsistentForGC(); 955 956 static void flushHeapDoesNotContainCache(); 957 static bool heapDoesNotContainCacheIsEmpty() { return s_heapDoesNotContainCache->isEmpty(); } 958 959 // Return true if the last GC found a pointer into a heap page 960 // during conservative scanning. 961 static bool lastGCWasConservative() { return s_lastGCWasConservative; } 962 963 private: 964 static Visitor* s_markingVisitor; 965 966 static CallbackStack* s_markingStack; 967 static CallbackStack* s_weakCallbackStack; 968 static HeapDoesNotContainCache* s_heapDoesNotContainCache; 969 static bool s_shutdownCalled; 970 static bool s_lastGCWasConservative; 971 friend class ThreadState; 972 }; 973 974 // The NoAllocationScope class is used in debug mode to catch unwanted 975 // allocations. E.g. allocations during GC. 976 template<ThreadAffinity Affinity> 977 class NoAllocationScope { 978 public: 979 NoAllocationScope() : m_active(true) { enter(); } 980 981 explicit NoAllocationScope(bool active) : m_active(active) { enter(); } 982 983 NoAllocationScope(const NoAllocationScope& other) : m_active(other.m_active) { enter(); } 984 985 NoAllocationScope& operator=(const NoAllocationScope& other) 986 { 987 release(); 988 m_active = other.m_active; 989 enter(); 990 return *this; 991 } 992 993 ~NoAllocationScope() { release(); } 994 995 void release() 996 { 997 if (m_active) { 998 ThreadStateFor<Affinity>::state()->leaveNoAllocationScope(); 999 m_active = false; 1000 } 1001 } 1002 1003 private: 1004 void enter() const 1005 { 1006 if (m_active) 1007 ThreadStateFor<Affinity>::state()->enterNoAllocationScope(); 1008 } 1009 1010 bool m_active; 1011 }; 1012 1013 // Base class for objects allocated in the Blink garbage-collected 1014 // heap. 1015 // 1016 // Defines a 'new' operator that allocates the memory in the 1017 // heap. 'delete' should not be called on objects that inherit from 1018 // GarbageCollected. 1019 // 1020 // Instances of GarbageCollected will *NOT* get finalized. Their 1021 // destructor will not be called. Therefore, only classes that have 1022 // trivial destructors with no semantic meaning (including all their 1023 // subclasses) should inherit from GarbageCollected. If there are 1024 // non-trival destructors in a given class or any of its subclasses, 1025 // GarbageCollectedFinalized should be used which guarantees that the 1026 // destructor is called on an instance when the garbage collector 1027 // determines that it is no longer reachable. 1028 template<typename T> 1029 class GarbageCollected { 1030 WTF_MAKE_NONCOPYABLE(GarbageCollected); 1031 1032 // For now direct allocation of arrays on the heap is not allowed. 1033 void* operator new[](size_t size); 1034 #if OS(WIN) && COMPILER(MSVC) 1035 // Due to some quirkiness in the MSVC compiler we have to provide 1036 // the delete[] operator in the GarbageCollected subclasses as it 1037 // is called when a class is exported in a DLL. 1038 protected: 1039 void operator delete[](void* p) 1040 { 1041 ASSERT_NOT_REACHED(); 1042 } 1043 #else 1044 void operator delete[](void* p); 1045 #endif 1046 public: 1047 typedef T GarbageCollectedBase; 1048 1049 void* operator new(size_t size) 1050 { 1051 return Heap::allocate<T>(size); 1052 } 1053 1054 void operator delete(void* p) 1055 { 1056 ASSERT_NOT_REACHED(); 1057 } 1058 1059 protected: 1060 GarbageCollected() 1061 { 1062 } 1063 }; 1064 1065 // Base class for objects allocated in the Blink garbage-collected 1066 // heap. 1067 // 1068 // Defines a 'new' operator that allocates the memory in the 1069 // heap. 'delete' should not be called on objects that inherit from 1070 // GarbageCollected. 1071 // 1072 // Instances of GarbageCollectedFinalized will have their destructor 1073 // called when the garbage collector determines that the object is no 1074 // longer reachable. 1075 template<typename T> 1076 class GarbageCollectedFinalized : public GarbageCollected<T> { 1077 WTF_MAKE_NONCOPYABLE(GarbageCollectedFinalized); 1078 1079 protected: 1080 // finalizeGarbageCollectedObject is called when the object is 1081 // freed from the heap. By default finalization means calling the 1082 // destructor on the object. finalizeGarbageCollectedObject can be 1083 // overridden to support calling the destructor of a 1084 // subclass. This is useful for objects without vtables that 1085 // require explicit dispatching. The name is intentionally a bit 1086 // long to make name conflicts less likely. 1087 void finalizeGarbageCollectedObject() 1088 { 1089 static_cast<T*>(this)->~T(); 1090 } 1091 1092 GarbageCollectedFinalized() { } 1093 ~GarbageCollectedFinalized() { } 1094 1095 template<typename U> friend struct HasFinalizer; 1096 template<typename U, bool> friend struct FinalizerTraitImpl; 1097 }; 1098 1099 // Base class for objects that are in the Blink garbage-collected heap 1100 // and are still reference counted. 1101 // 1102 // This class should be used sparingly and only to gradually move 1103 // objects from being reference counted to being managed by the blink 1104 // garbage collector. 1105 // 1106 // While the current reference counting keeps one of these objects 1107 // alive it will have a Persistent handle to itself allocated so we 1108 // will not reclaim the memory. When the reference count reaches 0 the 1109 // persistent handle will be deleted. When the garbage collector 1110 // determines that there are no other references to the object it will 1111 // be reclaimed and the destructor of the reclaimed object will be 1112 // called at that time. 1113 template<typename T> 1114 class RefCountedGarbageCollected : public GarbageCollectedFinalized<T> { 1115 WTF_MAKE_NONCOPYABLE(RefCountedGarbageCollected); 1116 1117 public: 1118 RefCountedGarbageCollected() 1119 : m_refCount(1) 1120 { 1121 makeKeepAlive(); 1122 } 1123 1124 // Implement method to increase reference count for use with 1125 // RefPtrs. 1126 // 1127 // In contrast to the normal WTF::RefCounted, the reference count 1128 // can reach 0 and increase again. This happens in the following 1129 // scenario: 1130 // 1131 // (1) The reference count becomes 0, but members, persistents, or 1132 // on-stack pointers keep references to the object. 1133 // 1134 // (2) The pointer is assigned to a RefPtr again and the reference 1135 // count becomes 1. 1136 // 1137 // In this case, we have to resurrect m_keepAlive. 1138 void ref() 1139 { 1140 if (UNLIKELY(!m_refCount)) { 1141 ASSERT(ThreadStateFor<ThreadingTrait<T>::Affinity>::state()->contains(reinterpret_cast<Address>(this))); 1142 makeKeepAlive(); 1143 } 1144 ++m_refCount; 1145 } 1146 1147 // Implement method to decrease reference count for use with 1148 // RefPtrs. 1149 // 1150 // In contrast to the normal WTF::RefCounted implementation, the 1151 // object itself is not deleted when the reference count reaches 1152 // 0. Instead, the keep-alive persistent handle is deallocated so 1153 // that the object can be reclaimed when the garbage collector 1154 // determines that there are no other references to the object. 1155 void deref() 1156 { 1157 ASSERT(m_refCount > 0); 1158 if (!--m_refCount) { 1159 delete m_keepAlive; 1160 m_keepAlive = 0; 1161 } 1162 } 1163 1164 bool hasOneRef() 1165 { 1166 return m_refCount == 1; 1167 } 1168 1169 protected: 1170 ~RefCountedGarbageCollected() { } 1171 1172 private: 1173 void makeKeepAlive() 1174 { 1175 ASSERT(!m_keepAlive); 1176 m_keepAlive = new Persistent<T>(static_cast<T*>(this)); 1177 } 1178 1179 int m_refCount; 1180 Persistent<T>* m_keepAlive; 1181 }; 1182 1183 template<typename T> 1184 T* adoptRefCountedGarbageCollected(T* ptr) 1185 { 1186 ASSERT(ptr->hasOneRef()); 1187 ptr->deref(); 1188 WTF::adopted(ptr); 1189 return ptr; 1190 } 1191 1192 // Classes that contain heap references but aren't themselves heap 1193 // allocated, have some extra macros available which allows their use 1194 // to be restricted to cases where the garbage collector is able 1195 // to discover their heap references. 1196 // 1197 // STACK_ALLOCATED(): Use if the object is only stack allocated. Heap objects 1198 // should be in Members but you do not need the trace method as they are on 1199 // the stack. (Down the line these might turn in to raw pointers, but for 1200 // now Members indicates that we have thought about them and explicitly 1201 // taken care of them.) 1202 // 1203 // DISALLOW_ALLOCATION(): Cannot be allocated with new operators but can 1204 // be a part object. If it has Members you need a trace method and the 1205 // containing object needs to call that trace method. 1206 // 1207 // ALLOW_ONLY_INLINE_ALLOCATION(): Allows only placement new operator. 1208 // This disallows general allocation of this object but allows to put 1209 // the object as a value object in collections. If these have Members you 1210 // need to have a trace method. That trace method will be called 1211 // automatically by the Heap collections. 1212 // 1213 #if COMPILER_SUPPORTS(CXX_DELETED_FUNCTIONS) 1214 #define DISALLOW_ALLOCATION() \ 1215 private: \ 1216 void* operator new(size_t) = delete; \ 1217 void* operator new(size_t, NotNullTag, void*) = delete; \ 1218 void* operator new(size_t, void*) = delete; 1219 1220 #define ALLOW_ONLY_INLINE_ALLOCATION() \ 1221 public: \ 1222 void* operator new(size_t, NotNullTag, void* location) { return location; } \ 1223 void* operator new(size_t, void* location) { return location; } \ 1224 private: \ 1225 void* operator new(size_t) = delete; 1226 1227 #define STATIC_ONLY(Type) \ 1228 private: \ 1229 Type() = delete; 1230 1231 #else 1232 1233 #define DISALLOW_ALLOCATION() \ 1234 private: \ 1235 void* operator new(size_t); \ 1236 void* operator new(size_t, NotNullTag, void*); \ 1237 void* operator new(size_t, void*) 1238 1239 #define ALLOW_ONLY_INLINE_ALLOCATION() \ 1240 public: \ 1241 void* operator new(size_t, NotNullTag, void* location) { return location; } \ 1242 void* operator new(size_t, void* location) { return location; } \ 1243 private: \ 1244 void* operator new(size_t); 1245 1246 #define STATIC_ONLY(Type) \ 1247 private: \ 1248 Type(); 1249 1250 #endif 1251 1252 1253 // These macros insert annotations that the Blink GC plugin for clang uses for 1254 // verification. STACK_ALLOCATED is used to declare that objects of this type 1255 // are always stack allocated. GC_PLUGIN_IGNORE is used to make the plugin 1256 // ignore a particular class or field when checking for proper usage. When using 1257 // GC_PLUGIN_IGNORE a bug-number should be provided as an argument where the 1258 // bug describes what needs to happen to remove the GC_PLUGIN_IGNORE again. 1259 #if COMPILER(CLANG) 1260 #define STACK_ALLOCATED() \ 1261 private: \ 1262 __attribute__((annotate("blink_stack_allocated"))) \ 1263 void* operator new(size_t) = delete; \ 1264 void* operator new(size_t, NotNullTag, void*) = delete; \ 1265 void* operator new(size_t, void*) = delete; 1266 1267 #define GC_PLUGIN_IGNORE(bug) \ 1268 __attribute__((annotate("blink_gc_plugin_ignore"))) 1269 #else 1270 #define STACK_ALLOCATED() DISALLOW_ALLOCATION() 1271 #define GC_PLUGIN_IGNORE(bug) 1272 #endif 1273 1274 NO_SANITIZE_ADDRESS 1275 void HeapObjectHeader::checkHeader() const 1276 { 1277 ASSERT(m_magic == magic); 1278 } 1279 1280 Address HeapObjectHeader::payload() 1281 { 1282 return reinterpret_cast<Address>(this) + objectHeaderSize; 1283 } 1284 1285 size_t HeapObjectHeader::payloadSize() 1286 { 1287 return size() - objectHeaderSize; 1288 } 1289 1290 Address HeapObjectHeader::payloadEnd() 1291 { 1292 return reinterpret_cast<Address>(this) + size(); 1293 } 1294 1295 NO_SANITIZE_ADDRESS 1296 void HeapObjectHeader::mark() 1297 { 1298 checkHeader(); 1299 m_size |= markBitMask; 1300 } 1301 1302 Address FinalizedHeapObjectHeader::payload() 1303 { 1304 return reinterpret_cast<Address>(this) + finalizedHeaderSize; 1305 } 1306 1307 size_t FinalizedHeapObjectHeader::payloadSize() 1308 { 1309 return size() - finalizedHeaderSize; 1310 } 1311 1312 template<typename Header> 1313 size_t ThreadHeap<Header>::allocationSizeFromSize(size_t size) 1314 { 1315 // Check the size before computing the actual allocation size. The 1316 // allocation size calculation can overflow for large sizes and 1317 // the check therefore has to happen before any calculation on the 1318 // size. 1319 RELEASE_ASSERT(size < maxHeapObjectSize); 1320 1321 // Add space for header. 1322 size_t allocationSize = size + sizeof(Header); 1323 // Align size with allocation granularity. 1324 allocationSize = (allocationSize + allocationMask) & ~allocationMask; 1325 return allocationSize; 1326 } 1327 1328 template<typename Header> 1329 Address ThreadHeap<Header>::allocate(size_t size, const GCInfo* gcInfo) 1330 { 1331 size_t allocationSize = allocationSizeFromSize(size); 1332 bool isLargeObject = allocationSize > blinkPageSize / 2; 1333 if (isLargeObject) 1334 return allocateLargeObject(allocationSize, gcInfo); 1335 if (m_remainingAllocationSize < allocationSize) 1336 return outOfLineAllocate(size, gcInfo); 1337 Address headerAddress = m_currentAllocationPoint; 1338 m_currentAllocationPoint += allocationSize; 1339 m_remainingAllocationSize -= allocationSize; 1340 Header* header = new (NotNull, headerAddress) Header(allocationSize, gcInfo); 1341 size_t payloadSize = allocationSize - sizeof(Header); 1342 stats().increaseObjectSpace(payloadSize); 1343 Address result = headerAddress + sizeof(*header); 1344 ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask)); 1345 // Unpoison the memory used for the object (payload). 1346 ASAN_UNPOISON_MEMORY_REGION(result, payloadSize); 1347 memset(result, 0, payloadSize); 1348 ASSERT(heapPageFromAddress(headerAddress + allocationSize - 1)); 1349 return result; 1350 } 1351 1352 // FIXME: Allocate objects that do not need finalization separately 1353 // and use separate sweeping to not have to check for finalizers. 1354 template<typename T> 1355 Address Heap::allocate(size_t size) 1356 { 1357 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(); 1358 ASSERT(state->isAllocationAllowed()); 1359 BaseHeap* heap = state->heap(HeapTrait<T>::index); 1360 Address addr = 1361 static_cast<typename HeapTrait<T>::HeapType*>(heap)->allocate(size, GCInfoTrait<T>::get()); 1362 return addr; 1363 } 1364 1365 // FIXME: Allocate objects that do not need finalization separately 1366 // and use separate sweeping to not have to check for finalizers. 1367 template<typename T> 1368 Address Heap::reallocate(void* previous, size_t size) 1369 { 1370 if (!size) { 1371 // If the new size is 0 this is equivalent to either 1372 // free(previous) or malloc(0). In both cases we do 1373 // nothing and return 0. 1374 return 0; 1375 } 1376 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(); 1377 ASSERT(state->isAllocationAllowed()); 1378 // FIXME: Currently only supports raw allocation on the 1379 // GeneralHeap. Hence we assume the header is a 1380 // FinalizedHeapObjectHeader. 1381 ASSERT(HeapTrait<T>::index == GeneralHeap); 1382 BaseHeap* heap = state->heap(HeapTrait<T>::index); 1383 Address address = static_cast<typename HeapTrait<T>::HeapType*>(heap)->allocate(size, GCInfoTrait<T>::get()); 1384 if (!previous) { 1385 // This is equivalent to malloc(size). 1386 return address; 1387 } 1388 FinalizedHeapObjectHeader* previousHeader = FinalizedHeapObjectHeader::fromPayload(previous); 1389 ASSERT(!previousHeader->hasFinalizer()); 1390 ASSERT(previousHeader->gcInfo() == GCInfoTrait<T>::get()); 1391 size_t copySize = previousHeader->payloadSize(); 1392 if (copySize > size) 1393 copySize = size; 1394 memcpy(address, previous, copySize); 1395 return address; 1396 } 1397 1398 class HeapAllocatorQuantizer { 1399 public: 1400 template<typename T> 1401 static size_t quantizedSize(size_t count) 1402 { 1403 RELEASE_ASSERT(count <= kMaxUnquantizedAllocation / sizeof(T)); 1404 return HeapTrait<T>::HeapType::roundedAllocationSize(count * sizeof(T)); 1405 } 1406 static const size_t kMaxUnquantizedAllocation = maxHeapObjectSize; 1407 }; 1408 1409 // This is a static-only class used as a trait on collections to make them heap allocated. 1410 // However see also HeapListHashSetAllocator. 1411 class HeapAllocator { 1412 public: 1413 typedef HeapAllocatorQuantizer Quantizer; 1414 typedef WebCore::Visitor Visitor; 1415 static const bool isGarbageCollected = true; 1416 1417 template <typename Return, typename Metadata> 1418 static Return backingMalloc(size_t size) 1419 { 1420 return malloc<Return, Metadata>(size); 1421 } 1422 template <typename Return, typename Metadata> 1423 static Return zeroedBackingMalloc(size_t size) 1424 { 1425 return malloc<Return, Metadata>(size); 1426 } 1427 template <typename Return, typename Metadata> 1428 static Return malloc(size_t size) 1429 { 1430 return reinterpret_cast<Return>(Heap::allocate<Metadata>(size)); 1431 } 1432 static void backingFree(void* address) { } 1433 static void free(void* address) { } 1434 template<typename T> 1435 static void* newArray(size_t bytes) 1436 { 1437 ASSERT_NOT_REACHED(); 1438 return 0; 1439 } 1440 1441 static void deleteArray(void* ptr) 1442 { 1443 ASSERT_NOT_REACHED(); 1444 } 1445 1446 static void markUsingGCInfo(Visitor* visitor, const void* buffer) 1447 { 1448 visitor->mark(buffer, FinalizedHeapObjectHeader::fromPayload(buffer)->traceCallback()); 1449 } 1450 1451 static void markNoTracing(Visitor* visitor, const void* t) { visitor->markNoTracing(t); } 1452 1453 template<typename T, typename Traits> 1454 static void trace(Visitor* visitor, T& t) 1455 { 1456 CollectionBackingTraceTrait<WTF::ShouldBeTraced<Traits>::value, Traits::weakHandlingFlag, WeakPointersActWeak, T, Traits>::trace(visitor, t); 1457 } 1458 1459 static void registerWeakMembers(Visitor* visitor, const void* closure, const void* object, WeakPointerCallback callback) 1460 { 1461 visitor->registerWeakMembers(closure, object, callback); 1462 } 1463 1464 template<typename T> 1465 struct ResultType { 1466 typedef T* Type; 1467 }; 1468 1469 // The WTF classes use Allocator::VectorBackingHelper in order to find a 1470 // class to template their backing allocation operation on. For off-heap 1471 // allocations the VectorBackingHelper is a dummy class, since the class is 1472 // not used during allocation of backing. For on-heap allocations this 1473 // typedef ensures that the allocation is done with the correct templated 1474 // instantiation of the allocation function. This ensures the correct GC 1475 // map is written when backing allocations take place. 1476 template<typename T, typename Traits> 1477 struct VectorBackingHelper { 1478 typedef HeapVectorBacking<T, Traits> Type; 1479 }; 1480 1481 // Like the VectorBackingHelper, but this type is used for HashSet and 1482 // HashMap, both of which are implemented using HashTable. 1483 template<typename Table> 1484 struct HashTableBackingHelper { 1485 typedef HeapHashTableBacking<Table> Type; 1486 }; 1487 1488 template<typename T> 1489 struct OtherType { 1490 typedef T* Type; 1491 }; 1492 1493 template<typename T> 1494 static T& getOther(T* other) 1495 { 1496 return *other; 1497 } 1498 1499 static bool isAlive(Visitor* visitor, void* pointer) { return visitor->isAlive(pointer); } 1500 1501 private: 1502 template<typename T, size_t u, typename V> friend class WTF::Vector; 1503 template<typename T, typename U, typename V, typename W> friend class WTF::HashSet; 1504 template<typename T, typename U, typename V, typename W, typename X, typename Y> friend class WTF::HashMap; 1505 }; 1506 1507 template<typename Value> 1508 static void traceListHashSetValue(Visitor* visitor, Value& value) 1509 { 1510 // We use the default hash traits for the value in the node, because 1511 // ListHashSet does not let you specify any specific ones. 1512 // We don't allow ListHashSet of WeakMember, so we set that one false 1513 // (there's an assert elsewhere), but we have to specify some value for the 1514 // strongify template argument, so we specify WeakPointersActWeak, 1515 // arbitrarily. 1516 CollectionBackingTraceTrait<WTF::ShouldBeTraced<WTF::HashTraits<Value> >::value, WTF::NoWeakHandlingInCollections, WeakPointersActWeak, Value, WTF::HashTraits<Value> >::trace(visitor, value); 1517 } 1518 1519 // The inline capacity is just a dummy template argument to match the off-heap 1520 // allocator. 1521 // This inherits from the static-only HeapAllocator trait class, but we do 1522 // declare pointers to instances. These pointers are always null, and no 1523 // objects are instantiated. 1524 template<typename ValueArg, size_t inlineCapacity> 1525 struct HeapListHashSetAllocator : public HeapAllocator { 1526 typedef HeapAllocator TableAllocator; 1527 typedef WTF::ListHashSetNode<ValueArg, HeapListHashSetAllocator> Node; 1528 1529 public: 1530 class AllocatorProvider { 1531 public: 1532 // For the heap allocation we don't need an actual allocator object, so we just 1533 // return null. 1534 HeapListHashSetAllocator* get() const { return 0; } 1535 1536 // No allocator object is needed. 1537 void createAllocatorIfNeeded() { } 1538 1539 // There is no allocator object in the HeapListHashSet (unlike in 1540 // the regular ListHashSet) so there is nothing to swap. 1541 void swap(AllocatorProvider& other) { } 1542 }; 1543 1544 void deallocate(void* dummy) { } 1545 1546 // This is not a static method even though it could be, because it 1547 // needs to match the one that the (off-heap) ListHashSetAllocator 1548 // has. The 'this' pointer will always be null. 1549 void* allocateNode() 1550 { 1551 COMPILE_ASSERT(!WTF::IsWeak<ValueArg>::value, WeakPointersInAListHashSetWillJustResultInNullEntriesInTheSetThatsNotWhatYouWantConsiderUsingLinkedHashSetInstead); 1552 return malloc<void*, Node>(sizeof(Node)); 1553 } 1554 1555 static void traceValue(Visitor* visitor, Node* node) 1556 { 1557 traceListHashSetValue(visitor, node->m_value); 1558 } 1559 }; 1560 1561 // FIXME: These should just be template aliases: 1562 // 1563 // template<typename T, size_t inlineCapacity = 0> 1564 // using HeapVector = Vector<T, inlineCapacity, HeapAllocator>; 1565 // 1566 // as soon as all the compilers we care about support that. 1567 // MSVC supports it only in MSVC 2013. 1568 template< 1569 typename KeyArg, 1570 typename MappedArg, 1571 typename HashArg = typename DefaultHash<KeyArg>::Hash, 1572 typename KeyTraitsArg = HashTraits<KeyArg>, 1573 typename MappedTraitsArg = HashTraits<MappedArg> > 1574 class HeapHashMap : public HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, HeapAllocator> { }; 1575 1576 template< 1577 typename ValueArg, 1578 typename HashArg = typename DefaultHash<ValueArg>::Hash, 1579 typename TraitsArg = HashTraits<ValueArg> > 1580 class HeapHashSet : public HashSet<ValueArg, HashArg, TraitsArg, HeapAllocator> { }; 1581 1582 template< 1583 typename ValueArg, 1584 typename HashArg = typename DefaultHash<ValueArg>::Hash, 1585 typename TraitsArg = HashTraits<ValueArg> > 1586 class HeapLinkedHashSet : public LinkedHashSet<ValueArg, HashArg, TraitsArg, HeapAllocator> { }; 1587 1588 template< 1589 typename ValueArg, 1590 size_t inlineCapacity = 0, // The inlineCapacity is just a dummy to match ListHashSet (off-heap). 1591 typename HashArg = typename DefaultHash<ValueArg>::Hash> 1592 class HeapListHashSet : public ListHashSet<ValueArg, inlineCapacity, HashArg, HeapListHashSetAllocator<ValueArg, inlineCapacity> > { }; 1593 1594 template< 1595 typename Value, 1596 typename HashFunctions = typename DefaultHash<Value>::Hash, 1597 typename Traits = HashTraits<Value> > 1598 class HeapHashCountedSet : public HashCountedSet<Value, HashFunctions, Traits, HeapAllocator> { }; 1599 1600 template<typename T, size_t inlineCapacity = 0> 1601 class HeapVector : public Vector<T, inlineCapacity, HeapAllocator> { 1602 public: 1603 HeapVector() { } 1604 1605 explicit HeapVector(size_t size) : Vector<T, inlineCapacity, HeapAllocator>(size) 1606 { 1607 } 1608 1609 HeapVector(size_t size, const T& val) : Vector<T, inlineCapacity, HeapAllocator>(size, val) 1610 { 1611 } 1612 1613 template<size_t otherCapacity> 1614 HeapVector(const HeapVector<T, otherCapacity>& other) 1615 : Vector<T, inlineCapacity, HeapAllocator>(other) 1616 { 1617 } 1618 1619 template<typename U> 1620 void append(const U& other) 1621 { 1622 Vector<T, inlineCapacity, HeapAllocator>::append(other); 1623 } 1624 1625 template<typename U, size_t otherCapacity> 1626 void appendVector(const HeapVector<U, otherCapacity>& other) 1627 { 1628 const Vector<U, otherCapacity, HeapAllocator>& otherVector = other; 1629 Vector<T, inlineCapacity, HeapAllocator>::appendVector(otherVector); 1630 } 1631 }; 1632 1633 template<typename T, size_t inlineCapacity = 0> 1634 class HeapDeque : public Deque<T, inlineCapacity, HeapAllocator> { 1635 public: 1636 HeapDeque() { } 1637 1638 explicit HeapDeque(size_t size) : Deque<T, inlineCapacity, HeapAllocator>(size) 1639 { 1640 } 1641 1642 HeapDeque(size_t size, const T& val) : Deque<T, inlineCapacity, HeapAllocator>(size, val) 1643 { 1644 } 1645 1646 // FIXME: Doesn't work if there is an inline buffer, due to crbug.com/360572 1647 HeapDeque<T, 0>& operator=(const HeapDeque& other) 1648 { 1649 HeapDeque<T> copy(other); 1650 swap(copy); 1651 return *this; 1652 } 1653 1654 // FIXME: Doesn't work if there is an inline buffer, due to crbug.com/360572 1655 inline void swap(HeapDeque& other) 1656 { 1657 Deque<T, inlineCapacity, HeapAllocator>::swap(other); 1658 } 1659 1660 template<size_t otherCapacity> 1661 HeapDeque(const HeapDeque<T, otherCapacity>& other) 1662 : Deque<T, inlineCapacity, HeapAllocator>(other) 1663 { 1664 } 1665 1666 template<typename U> 1667 void append(const U& other) 1668 { 1669 Deque<T, inlineCapacity, HeapAllocator>::append(other); 1670 } 1671 }; 1672 1673 template<typename T> 1674 struct ThreadingTrait<Member<T> > { 1675 static const ThreadAffinity Affinity = ThreadingTrait<T>::Affinity; 1676 }; 1677 1678 template<typename T> 1679 struct ThreadingTrait<WeakMember<T> > { 1680 static const ThreadAffinity Affinity = ThreadingTrait<T>::Affinity; 1681 }; 1682 1683 template<typename Key, typename Value, typename T, typename U, typename V> 1684 struct ThreadingTrait<HashMap<Key, Value, T, U, V, HeapAllocator> > { 1685 static const ThreadAffinity Affinity = 1686 (ThreadingTrait<Key>::Affinity == MainThreadOnly) 1687 && (ThreadingTrait<Value>::Affinity == MainThreadOnly) ? MainThreadOnly : AnyThread; 1688 }; 1689 1690 template<typename First, typename Second> 1691 struct ThreadingTrait<WTF::KeyValuePair<First, Second> > { 1692 static const ThreadAffinity Affinity = 1693 (ThreadingTrait<First>::Affinity == MainThreadOnly) 1694 && (ThreadingTrait<Second>::Affinity == MainThreadOnly) ? MainThreadOnly : AnyThread; 1695 }; 1696 1697 template<typename T, typename U, typename V> 1698 struct ThreadingTrait<HashSet<T, U, V, HeapAllocator> > { 1699 static const ThreadAffinity Affinity = ThreadingTrait<T>::Affinity; 1700 }; 1701 1702 1703 template<typename T, size_t inlineCapacity> 1704 struct ThreadingTrait<Vector<T, inlineCapacity, HeapAllocator> > { 1705 static const ThreadAffinity Affinity = ThreadingTrait<T>::Affinity; 1706 }; 1707 1708 template<typename T, typename Traits> 1709 struct ThreadingTrait<HeapVectorBacking<T, Traits> > { 1710 static const ThreadAffinity Affinity = ThreadingTrait<T>::Affinity; 1711 }; 1712 1713 template<typename T, size_t inlineCapacity> 1714 struct ThreadingTrait<Deque<T, inlineCapacity, HeapAllocator> > { 1715 static const ThreadAffinity Affinity = ThreadingTrait<T>::Affinity; 1716 }; 1717 1718 template<typename T, typename U, typename V> 1719 struct ThreadingTrait<HashCountedSet<T, U, V, HeapAllocator> > { 1720 static const ThreadAffinity Affinity = ThreadingTrait<T>::Affinity; 1721 }; 1722 1723 template<typename Table> 1724 struct ThreadingTrait<HeapHashTableBacking<Table> > { 1725 typedef typename Table::KeyType Key; 1726 typedef typename Table::ValueType Value; 1727 static const ThreadAffinity Affinity = 1728 (ThreadingTrait<Key>::Affinity == MainThreadOnly) 1729 && (ThreadingTrait<Value>::Affinity == MainThreadOnly) ? MainThreadOnly : AnyThread; 1730 }; 1731 1732 template<typename T, typename U, typename V, typename W, typename X> 1733 struct ThreadingTrait<HeapHashMap<T, U, V, W, X> > : public ThreadingTrait<HashMap<T, U, V, W, X, HeapAllocator> > { }; 1734 1735 template<typename T, typename U, typename V> 1736 struct ThreadingTrait<HeapHashSet<T, U, V> > : public ThreadingTrait<HashSet<T, U, V, HeapAllocator> > { }; 1737 1738 template<typename T, size_t inlineCapacity> 1739 struct ThreadingTrait<HeapVector<T, inlineCapacity> > : public ThreadingTrait<Vector<T, inlineCapacity, HeapAllocator> > { }; 1740 1741 template<typename T, size_t inlineCapacity> 1742 struct ThreadingTrait<HeapDeque<T, inlineCapacity> > : public ThreadingTrait<Deque<T, inlineCapacity, HeapAllocator> > { }; 1743 1744 template<typename T, typename U, typename V> 1745 struct ThreadingTrait<HeapHashCountedSet<T, U, V> > : public ThreadingTrait<HashCountedSet<T, U, V, HeapAllocator> > { }; 1746 1747 // The standard implementation of GCInfoTrait<T>::get() just returns a static 1748 // from the class T, but we can't do that for HashMap, HashSet, Vector, etc. 1749 // because they are in WTF and know nothing of GCInfos. Instead we have a 1750 // specialization of GCInfoTrait for these four classes here. 1751 1752 template<typename Key, typename Value, typename T, typename U, typename V> 1753 struct GCInfoTrait<HashMap<Key, Value, T, U, V, HeapAllocator> > { 1754 static const GCInfo* get() 1755 { 1756 typedef HashMap<Key, Value, T, U, V, HeapAllocator> TargetType; 1757 static const GCInfo info = { 1758 TraceTrait<TargetType>::trace, 1759 0, 1760 false, // HashMap needs no finalizer. 1761 WTF::IsPolymorphic<TargetType>::value, 1762 #if ENABLE(GC_TRACING) 1763 TypenameStringTrait<TargetType>::get() 1764 #endif 1765 }; 1766 return &info; 1767 } 1768 }; 1769 1770 template<typename T, typename U, typename V> 1771 struct GCInfoTrait<HashSet<T, U, V, HeapAllocator> > { 1772 static const GCInfo* get() 1773 { 1774 typedef HashSet<T, U, V, HeapAllocator> TargetType; 1775 static const GCInfo info = { 1776 TraceTrait<TargetType>::trace, 1777 0, 1778 false, // HashSet needs no finalizer. 1779 WTF::IsPolymorphic<TargetType>::value, 1780 #if ENABLE(GC_TRACING) 1781 TypenameStringTrait<TargetType>::get() 1782 #endif 1783 }; 1784 return &info; 1785 } 1786 }; 1787 1788 template<typename T, typename U, typename V> 1789 struct GCInfoTrait<LinkedHashSet<T, U, V, HeapAllocator> > { 1790 static const GCInfo* get() 1791 { 1792 typedef LinkedHashSet<T, U, V, HeapAllocator> TargetType; 1793 static const GCInfo info = { 1794 TraceTrait<TargetType>::trace, 1795 LinkedHashSet<T, U, V, HeapAllocator>::finalize, 1796 true, // Needs finalization. The anchor needs to unlink itself from the chain. 1797 WTF::IsPolymorphic<TargetType>::value, 1798 #if ENABLE(GC_TRACING) 1799 TypenameStringTrait<TargetType>::get() 1800 #endif 1801 }; 1802 return &info; 1803 } 1804 }; 1805 1806 template<typename ValueArg, size_t inlineCapacity, typename U> 1807 struct GCInfoTrait<ListHashSet<ValueArg, inlineCapacity, U, HeapListHashSetAllocator<ValueArg, inlineCapacity> > > { 1808 static const GCInfo* get() 1809 { 1810 typedef WTF::ListHashSet<ValueArg, inlineCapacity, U, HeapListHashSetAllocator<ValueArg, inlineCapacity> > TargetType; 1811 static const GCInfo info = { 1812 TraceTrait<TargetType>::trace, 1813 0, 1814 false, // ListHashSet needs no finalization though its backing might. 1815 false, // no vtable. 1816 #if ENABLE(GC_TRACING) 1817 TypenameStringTrait<TargetType>::get() 1818 #endif 1819 }; 1820 return &info; 1821 } 1822 }; 1823 1824 template<typename T, typename Allocator> 1825 struct GCInfoTrait<WTF::ListHashSetNode<T, Allocator> > { 1826 static const GCInfo* get() 1827 { 1828 typedef WTF::ListHashSetNode<T, Allocator> TargetType; 1829 static const GCInfo info = { 1830 TraceTrait<TargetType>::trace, 1831 TargetType::finalize, 1832 WTF::HashTraits<T>::needsDestruction, // The node needs destruction if its data does. 1833 false, // no vtable. 1834 #if ENABLE(GC_TRACING) 1835 TypenameStringTrait<TargetType>::get() 1836 #endif 1837 }; 1838 return &info; 1839 } 1840 }; 1841 1842 template<typename T> 1843 struct GCInfoTrait<Vector<T, 0, HeapAllocator> > { 1844 static const GCInfo* get() 1845 { 1846 #if ENABLE(GC_TRACING) 1847 typedef Vector<T, 0, HeapAllocator> TargetType; 1848 #endif 1849 static const GCInfo info = { 1850 TraceTrait<Vector<T, 0, HeapAllocator> >::trace, 1851 0, 1852 false, // Vector needs no finalizer if it has no inline capacity. 1853 WTF::IsPolymorphic<Vector<T, 0, HeapAllocator> >::value, 1854 #if ENABLE(GC_TRACING) 1855 TypenameStringTrait<TargetType>::get() 1856 #endif 1857 }; 1858 return &info; 1859 } 1860 }; 1861 1862 template<typename T, size_t inlineCapacity> 1863 struct FinalizerTrait<Vector<T, inlineCapacity, HeapAllocator> > : public FinalizerTraitImpl<Vector<T, inlineCapacity, HeapAllocator>, true> { }; 1864 1865 template<typename T, size_t inlineCapacity> 1866 struct GCInfoTrait<Vector<T, inlineCapacity, HeapAllocator> > { 1867 static const GCInfo* get() 1868 { 1869 typedef Vector<T, inlineCapacity, HeapAllocator> TargetType; 1870 static const GCInfo info = { 1871 TraceTrait<TargetType>::trace, 1872 FinalizerTrait<TargetType>::finalize, 1873 // Finalizer is needed to destruct things stored in the inline capacity. 1874 inlineCapacity && VectorTraits<T>::needsDestruction, 1875 WTF::IsPolymorphic<TargetType>::value, 1876 #if ENABLE(GC_TRACING) 1877 TypenameStringTrait<TargetType>::get() 1878 #endif 1879 }; 1880 return &info; 1881 } 1882 }; 1883 1884 template<typename T> 1885 struct GCInfoTrait<Deque<T, 0, HeapAllocator> > { 1886 static const GCInfo* get() 1887 { 1888 typedef Deque<T, 0, HeapAllocator> TargetType; 1889 static const GCInfo info = { 1890 TraceTrait<TargetType>::trace, 1891 0, 1892 false, // Deque needs no finalizer if it has no inline capacity. 1893 WTF::IsPolymorphic<TargetType>::value, 1894 #if ENABLE(GC_TRACING) 1895 TypenameStringTrait<TargetType>::get() 1896 #endif 1897 }; 1898 return &info; 1899 } 1900 static const GCInfo info; 1901 }; 1902 1903 template<typename T, typename U, typename V> 1904 struct GCInfoTrait<HashCountedSet<T, U, V, HeapAllocator> > { 1905 static const GCInfo* get() 1906 { 1907 typedef HashCountedSet<T, U, V, HeapAllocator> TargetType; 1908 static const GCInfo info = { 1909 TraceTrait<TargetType>::trace, 1910 0, 1911 false, // HashCountedSet is just a HashTable, and needs no finalizer. 1912 WTF::IsPolymorphic<TargetType>::value, 1913 #if ENABLE(GC_TRACING) 1914 TypenameStringTrait<TargetType>::get() 1915 #endif 1916 }; 1917 return &info; 1918 } 1919 static const GCInfo info; 1920 }; 1921 1922 template<typename T, size_t inlineCapacity> 1923 struct FinalizerTrait<Deque<T, inlineCapacity, HeapAllocator> > : public FinalizerTraitImpl<Deque<T, inlineCapacity, HeapAllocator>, true> { }; 1924 1925 template<typename T, size_t inlineCapacity> 1926 struct GCInfoTrait<Deque<T, inlineCapacity, HeapAllocator> > { 1927 static const GCInfo* get() 1928 { 1929 typedef Deque<T, inlineCapacity, HeapAllocator> TargetType; 1930 static const GCInfo info = { 1931 TraceTrait<TargetType>::trace, 1932 FinalizerTrait<TargetType>::finalize, 1933 // Finalizer is needed to destruct things stored in the inline capacity. 1934 inlineCapacity && VectorTraits<T>::needsDestruction, 1935 WTF::IsPolymorphic<TargetType>::value, 1936 #if ENABLE(GC_TRACING) 1937 TypenameStringTrait<TargetType>::get() 1938 #endif 1939 }; 1940 return &info; 1941 } 1942 static const GCInfo info; 1943 }; 1944 1945 template<typename T, typename Traits> 1946 struct GCInfoTrait<HeapVectorBacking<T, Traits> > { 1947 static const GCInfo* get() 1948 { 1949 typedef HeapVectorBacking<T, Traits> TargetType; 1950 static const GCInfo info = { 1951 TraceTrait<TargetType>::trace, 1952 FinalizerTrait<TargetType>::finalize, 1953 Traits::needsDestruction, 1954 false, // We don't support embedded objects in HeapVectors with vtables. 1955 #if ENABLE(GC_TRACING) 1956 TypenameStringTrait<TargetType>::get() 1957 #endif 1958 }; 1959 return &info; 1960 } 1961 }; 1962 1963 template<typename Table> 1964 struct GCInfoTrait<HeapHashTableBacking<Table> > { 1965 static const GCInfo* get() 1966 { 1967 typedef HeapHashTableBacking<Table> TargetType; 1968 static const GCInfo info = { 1969 TraceTrait<TargetType>::trace, 1970 HeapHashTableBacking<Table>::finalize, 1971 Table::ValueTraits::needsDestruction, 1972 WTF::IsPolymorphic<TargetType>::value, 1973 #if ENABLE(GC_TRACING) 1974 TypenameStringTrait<TargetType>::get() 1975 #endif 1976 }; 1977 return &info; 1978 } 1979 }; 1980 1981 // This is for tracing inside collections that have special support for weak 1982 // pointers. This is normally handled through the HashTraits, but it is not 1983 // feasible to add methods for handling tracing to the hash traits of WTF 1984 // classes like KeyValuePair, which is used to implement HashMap. This trait 1985 // lets us add custom handling for such classes. 1986 template<WTF::WeakHandlingFlag weakHandlingFlag, ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits> 1987 struct TraceInCollectionTrait; 1988 1989 // Catch-all for types that have a way to trace that don't have special 1990 // handling for weakness in collections. This means that if this type 1991 // contains WeakMember fields, they will simply be zeroed, but the entry 1992 // will not be removed from the collection. This always happens for 1993 // things in vectors, which don't currently support special handling of 1994 // weak elements. 1995 template<ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits> 1996 struct TraceInCollectionTrait<WTF::NoWeakHandlingInCollections, strongify, T, Traits> { 1997 static void trace(Visitor* visitor, T& t) 1998 { 1999 TraceTrait<T>::trace(visitor, &t); 2000 } 2001 }; 2002 2003 // Catch-all for things that have HashTrait support for tracing with weakness. 2004 template<ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits> 2005 struct TraceInCollectionTrait<WTF::WeakHandlingInCollections, strongify, T, Traits> { 2006 static void trace(Visitor* visitor, T& t) 2007 { 2008 Traits::traceInCollection(visitor, t, strongify); 2009 } 2010 }; 2011 2012 // Vector backing that needs marking. We don't support weak members in vectors. 2013 template<ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits> 2014 struct TraceInCollectionTrait<WTF::NoWeakHandlingInCollections, strongify, HeapVectorBacking<T, Traits>, void> { 2015 static void trace(Visitor* visitor, void* self) 2016 { 2017 // The allocator can oversize the allocation a little, according to 2018 // the allocation granularity. The extra size is included in the 2019 // payloadSize call below, since there is nowhere to store the 2020 // originally allocated memory. This assert ensures that visiting the 2021 // last bit of memory can't cause trouble. 2022 COMPILE_ASSERT(!WTF::ShouldBeTraced<Traits>::value || sizeof(T) > allocationGranularity || Traits::canInitializeWithMemset, HeapOverallocationCanCauseSpuriousVisits); 2023 2024 T* array = reinterpret_cast<T*>(self); 2025 WebCore::FinalizedHeapObjectHeader* header = WebCore::FinalizedHeapObjectHeader::fromPayload(self); 2026 // Use the payload size as recorded by the heap to determine how many 2027 // elements to mark. 2028 size_t length = header->payloadSize() / sizeof(T); 2029 for (size_t i = 0; i < length; i++) 2030 CollectionBackingTraceTrait<WTF::ShouldBeTraced<Traits>::value, Traits::weakHandlingFlag, WeakPointersActStrong, T, Traits>::trace(visitor, array[i]); 2031 } 2032 }; 2033 2034 // Almost all hash table backings are visited with this specialization. 2035 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Table> 2036 struct TraceInCollectionTrait<WTF::NoWeakHandlingInCollections, strongify, HeapHashTableBacking<Table>, void> { 2037 typedef typename Table::ValueType Value; 2038 typedef typename Table::ValueTraits Traits; 2039 static void trace(Visitor* visitor, void* self) 2040 { 2041 Value* array = reinterpret_cast<Value*>(self); 2042 WebCore::FinalizedHeapObjectHeader* header = WebCore::FinalizedHeapObjectHeader::fromPayload(self); 2043 size_t length = header->payloadSize() / sizeof(Value); 2044 for (size_t i = 0; i < length; i++) { 2045 if (!WTF::HashTableHelper<Value, typename Table::ExtractorType, typename Table::KeyTraitsType>::isEmptyOrDeletedBucket(array[i])) 2046 CollectionBackingTraceTrait<WTF::ShouldBeTraced<Traits>::value, Traits::weakHandlingFlag, strongify, Value, Traits>::trace(visitor, array[i]); 2047 } 2048 } 2049 }; 2050 2051 // This specialization of TraceInCollectionTrait is for the backing of 2052 // HeapListHashSet. This is for the case that we find a reference to the 2053 // backing from the stack. That probably means we have a GC while we are in a 2054 // ListHashSet method since normal API use does not put pointers to the backing 2055 // on the stack. 2056 template<ShouldWeakPointersBeMarkedStrongly strongify, typename NodeContents, size_t inlineCapacity, typename T, typename U, typename V, typename W, typename X, typename Y> 2057 struct TraceInCollectionTrait<WTF::NoWeakHandlingInCollections, strongify, HeapHashTableBacking<WTF::HashTable<WTF::ListHashSetNode<NodeContents, HeapListHashSetAllocator<T, inlineCapacity> >*, U, V, W, X, Y, HeapAllocator> >, void> { 2058 typedef WTF::ListHashSetNode<NodeContents, HeapListHashSetAllocator<T, inlineCapacity> > Node; 2059 typedef WTF::HashTable<Node*, U, V, W, X, Y, HeapAllocator> Table; 2060 static void trace(Visitor* visitor, void* self) 2061 { 2062 Node** array = reinterpret_cast<Node**>(self); 2063 WebCore::FinalizedHeapObjectHeader* header = WebCore::FinalizedHeapObjectHeader::fromPayload(self); 2064 size_t length = header->payloadSize() / sizeof(Node*); 2065 for (size_t i = 0; i < length; i++) { 2066 if (!WTF::HashTableHelper<Node*, typename Table::ExtractorType, typename Table::KeyTraitsType>::isEmptyOrDeletedBucket(array[i])) { 2067 traceListHashSetValue(visitor, array[i]->m_value); 2068 // Just mark the node without tracing because we already traced 2069 // the contents, and there is no need to trace the next and 2070 // prev fields since iterating over the hash table backing will 2071 // find the whole chain. 2072 visitor->markNoTracing(array[i]); 2073 } 2074 } 2075 } 2076 }; 2077 2078 // Key value pairs, as used in HashMap. To disambiguate template choice we have 2079 // to have two versions, first the one with no special weak handling, then the 2080 // one with weak handling. 2081 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Key, typename Value, typename Traits> 2082 struct TraceInCollectionTrait<WTF::NoWeakHandlingInCollections, strongify, WTF::KeyValuePair<Key, Value>, Traits> { 2083 static void trace(Visitor* visitor, WTF::KeyValuePair<Key, Value>& self) 2084 { 2085 ASSERT(WTF::ShouldBeTraced<Traits>::value); 2086 CollectionBackingTraceTrait<WTF::ShouldBeTraced<typename Traits::KeyTraits>::value, WTF::NoWeakHandlingInCollections, strongify, Key, typename Traits::KeyTraits>::trace(visitor, self.key); 2087 CollectionBackingTraceTrait<WTF::ShouldBeTraced<typename Traits::ValueTraits>::value, WTF::NoWeakHandlingInCollections, strongify, Value, typename Traits::ValueTraits>::trace(visitor, self.value); 2088 } 2089 }; 2090 2091 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Key, typename Value, typename Traits> 2092 struct TraceInCollectionTrait<WTF::WeakHandlingInCollections, strongify, WTF::KeyValuePair<Key, Value>, Traits> { 2093 static void trace(Visitor* visitor, WTF::KeyValuePair<Key, Value>& self) 2094 { 2095 ASSERT(WTF::ShouldBeTraced<Traits>::value || strongify == WeakPointersActStrong); 2096 CollectionBackingTraceTrait<WTF::ShouldBeTraced<typename Traits::KeyTraits>::value, Traits::KeyTraits::weakHandlingFlag, strongify, Key, typename Traits::KeyTraits>::trace(visitor, self.key); 2097 CollectionBackingTraceTrait<WTF::ShouldBeTraced<typename Traits::ValueTraits>::value, Traits::ValueTraits::weakHandlingFlag, strongify, Value, typename Traits::ValueTraits>::trace(visitor, self.value); 2098 } 2099 }; 2100 2101 // Nodes used by LinkedHashSet. Again we need two versions to disambiguate the 2102 // template. 2103 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Value, typename Traits> 2104 struct TraceInCollectionTrait<WTF::NoWeakHandlingInCollections, strongify, WTF::LinkedHashSetNode<Value>, Traits> { 2105 static void trace(Visitor* visitor, WTF::LinkedHashSetNode<Value>& self) 2106 { 2107 ASSERT(WTF::ShouldBeTraced<Traits>::value); 2108 TraceTrait<Value>::trace(visitor, &self.m_value); 2109 } 2110 }; 2111 2112 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Value, typename Traits> 2113 struct TraceInCollectionTrait<WTF::WeakHandlingInCollections, strongify, WTF::LinkedHashSetNode<Value>, Traits> { 2114 static void trace(Visitor* visitor, WTF::LinkedHashSetNode<Value>& self) 2115 { 2116 ASSERT(WTF::ShouldBeTraced<Traits>::value || strongify == WeakPointersActStrong); 2117 TraceInCollectionTrait<WTF::WeakHandlingInCollections, strongify, Value, typename Traits::ValueTraits>::trace(visitor, self.m_value); 2118 } 2119 }; 2120 2121 // ListHashSetNode pointers (a ListHashSet is implemented as a hash table of these pointers). 2122 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Value, size_t inlineCapacity, typename Traits> 2123 struct TraceInCollectionTrait<WTF::NoWeakHandlingInCollections, strongify, WTF::ListHashSetNode<Value, HeapListHashSetAllocator<Value, inlineCapacity> >*, Traits> { 2124 typedef WTF::ListHashSetNode<Value, HeapListHashSetAllocator<Value, inlineCapacity> > Node; 2125 static void trace(Visitor* visitor, Node* node) 2126 { 2127 traceListHashSetValue(visitor, node->m_value); 2128 // Just mark the node without tracing because we already traced the 2129 // contents, and there is no need to trace the next and prev fields 2130 // since iterating over the hash table backing will find the whole 2131 // chain. 2132 visitor->markNoTracing(node); 2133 } 2134 }; 2135 2136 // FIXME: oilpan: Perhaps we don't need this any more. 2137 // Catch-all for things that don't need marking and have no weak pointers. We 2138 // do nothing, even if WeakPointersActStrong. 2139 template<ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename U> 2140 struct CollectionBackingTraceTrait<false, WTF::NoWeakHandlingInCollections, strongify, T, U> { 2141 static void trace(Visitor*, T&) { } 2142 }; 2143 2144 // Catch-all for things that don't need marking. They have weak pointers, but 2145 // we are not marking weak pointers in this object in this GC. 2146 template<typename T, typename U> 2147 struct CollectionBackingTraceTrait<false, WTF::WeakHandlingInCollections, WeakPointersActWeak, T, U> { 2148 static void trace(Visitor*, T&) { } 2149 }; 2150 2151 // Things that need marking because they contain weak pointers that we are making 2152 // strong for this GC because there is an outstanding iterator that would be 2153 // disturbed if we started removing entries from the colletion. 2154 template<typename T, typename Traits> 2155 struct CollectionBackingTraceTrait<false, WTF::WeakHandlingInCollections, WeakPointersActStrong, T, Traits> { 2156 static void trace(Visitor* visitor, T& t) { TraceInCollectionTrait<WTF::WeakHandlingInCollections, WeakPointersActStrong, T, Traits>::trace(visitor, t); } 2157 static void trace(Visitor* visitor, void* t) { TraceInCollectionTrait<WTF::WeakHandlingInCollections, WeakPointersActStrong, T, Traits>::trace(visitor, t); } 2158 }; 2159 2160 // Things that need marking because they contain strong pointers 2161 template<WTF::WeakHandlingFlag weakHandlingFlag, ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits> 2162 struct CollectionBackingTraceTrait<true, weakHandlingFlag, strongify, T, Traits> { 2163 static void trace(Visitor* visitor, T& t) { TraceInCollectionTrait<weakHandlingFlag, strongify, T, Traits>::trace(visitor, t); } 2164 template <typename U> 2165 static void trace(Visitor* visitor, U* t) { TraceInCollectionTrait<weakHandlingFlag, strongify, T, Traits>::trace(visitor, T(t)); } 2166 }; 2167 2168 template<typename T> struct WeakHandlingHashTraits : WTF::SimpleClassHashTraits<T> { 2169 // We want to treat the object as a weak object in the sense that it can 2170 // disappear from hash sets and hash maps. 2171 static const WTF::WeakHandlingFlag weakHandlingFlag = WTF::WeakHandlingInCollections; 2172 // Normally whether or not an object needs tracing is inferred 2173 // automatically from the presence of the trace method, but we don't 2174 // necessarily have a trace method, and we may not need one because T 2175 // can perhaps only be allocated inside collections, never as indpendent 2176 // objects. Explicitly mark this as needing tracing and it will be traced 2177 // in collections using the traceInCollection method, which it must have. 2178 template<typename U = void> struct NeedsTracingLazily { 2179 static const bool value = true; 2180 }; 2181 // This method is called at the end of GC to test which elements should be 2182 // removed from the collection. It returns true if the object contains 2183 // non-live pointers. If this method incorrectly returns false, then we can 2184 // have dangerous dangling pointers! 2185 template<typename Visitor> static bool shouldRemoveFromCollection(Visitor* visitor, T& t) 2186 { 2187 return t.shouldRemoveFromCollection(visitor); 2188 } 2189 // The traceInCollection method traces differently depending on whether we 2190 // are strongifying the trace operation. We strongify the trace operation 2191 // when there are active iterators on the object. In this case all 2192 // WeakMembers are marked like strong members so that elements do not 2193 // suddenly disappear during iteration. 2194 static void traceInCollection(WebCore::Visitor* visitor, T& t, WebCore::ShouldWeakPointersBeMarkedStrongly strongify) 2195 { 2196 t.traceInCollection(visitor, strongify); 2197 } 2198 }; 2199 2200 template<typename T, typename Traits> 2201 struct TraceTrait<HeapVectorBacking<T, Traits> > { 2202 typedef HeapVectorBacking<T, Traits> Backing; 2203 static void trace(Visitor* visitor, void* self) 2204 { 2205 COMPILE_ASSERT(!WTF::IsWeak<T>::value, WeDontSupportWeaknessInHeapVectorsOrDeques); 2206 if (WTF::ShouldBeTraced<Traits>::value) 2207 TraceInCollectionTrait<WTF::NoWeakHandlingInCollections, WeakPointersActWeak, HeapVectorBacking<T, Traits>, void>::trace(visitor, self); 2208 } 2209 static void mark(Visitor* visitor, const Backing* backing) 2210 { 2211 visitor->mark(backing, &trace); 2212 } 2213 static void checkGCInfo(Visitor* visitor, const Backing* backing) 2214 { 2215 #ifndef NDEBUG 2216 visitor->checkGCInfo(const_cast<Backing*>(backing), GCInfoTrait<Backing>::get()); 2217 #endif 2218 } 2219 }; 2220 2221 // The trace trait for the heap hashtable backing is used when we find a 2222 // direct pointer to the backing from the conservative stack scanner. This 2223 // normally indicates that there is an ongoing iteration over the table, and so 2224 // we disable weak processing of table entries. When the backing is found 2225 // through the owning hash table we mark differently, in order to do weak 2226 // processing. 2227 template<typename Table> 2228 struct TraceTrait<HeapHashTableBacking<Table> > { 2229 typedef HeapHashTableBacking<Table> Backing; 2230 typedef typename Table::ValueTraits Traits; 2231 static void trace(Visitor* visitor, void* self) 2232 { 2233 if (WTF::ShouldBeTraced<Traits>::value || Traits::weakHandlingFlag == WTF::WeakHandlingInCollections) 2234 TraceInCollectionTrait<WTF::NoWeakHandlingInCollections, WeakPointersActStrong, Backing, void>::trace(visitor, self); 2235 } 2236 static void mark(Visitor* visitor, const Backing* backing) 2237 { 2238 if (WTF::ShouldBeTraced<Traits>::value || Traits::weakHandlingFlag == WTF::WeakHandlingInCollections) 2239 visitor->mark(backing, &trace); 2240 else 2241 visitor->markNoTracing(backing); // If we know the trace function will do nothing there is no need to call it. 2242 } 2243 static void checkGCInfo(Visitor* visitor, const Backing* backing) 2244 { 2245 #ifndef NDEBUG 2246 visitor->checkGCInfo(const_cast<Backing*>(backing), GCInfoTrait<Backing>::get()); 2247 #endif 2248 } 2249 }; 2250 2251 template<typename Table> 2252 void HeapHashTableBacking<Table>::finalize(void* pointer) 2253 { 2254 typedef typename Table::ValueType Value; 2255 ASSERT(Table::ValueTraits::needsDestruction); 2256 FinalizedHeapObjectHeader* header = FinalizedHeapObjectHeader::fromPayload(pointer); 2257 // Use the payload size as recorded by the heap to determine how many 2258 // elements to finalize. 2259 size_t length = header->payloadSize() / sizeof(Value); 2260 Value* table = reinterpret_cast<Value*>(pointer); 2261 for (unsigned i = 0; i < length; i++) { 2262 if (!Table::isEmptyOrDeletedBucket(table[i])) 2263 table[i].~Value(); 2264 } 2265 } 2266 2267 template<typename T, typename U, typename V, typename W, typename X> 2268 struct GCInfoTrait<HeapHashMap<T, U, V, W, X> > : public GCInfoTrait<HashMap<T, U, V, W, X, HeapAllocator> > { }; 2269 template<typename T, typename U, typename V> 2270 struct GCInfoTrait<HeapHashSet<T, U, V> > : public GCInfoTrait<HashSet<T, U, V, HeapAllocator> > { }; 2271 template<typename T, typename U, typename V> 2272 struct GCInfoTrait<HeapLinkedHashSet<T, U, V> > : public GCInfoTrait<LinkedHashSet<T, U, V, HeapAllocator> > { }; 2273 template<typename T, size_t inlineCapacity, typename U> 2274 struct GCInfoTrait<HeapListHashSet<T, inlineCapacity, U> > : public GCInfoTrait<ListHashSet<T, inlineCapacity, U, HeapListHashSetAllocator<T, inlineCapacity> > > { }; 2275 template<typename T, size_t inlineCapacity> 2276 struct GCInfoTrait<HeapVector<T, inlineCapacity> > : public GCInfoTrait<Vector<T, inlineCapacity, HeapAllocator> > { }; 2277 template<typename T, size_t inlineCapacity> 2278 struct GCInfoTrait<HeapDeque<T, inlineCapacity> > : public GCInfoTrait<Deque<T, inlineCapacity, HeapAllocator> > { }; 2279 template<typename T, typename U, typename V> 2280 struct GCInfoTrait<HeapHashCountedSet<T, U, V> > : public GCInfoTrait<HashCountedSet<T, U, V, HeapAllocator> > { }; 2281 2282 template<typename T> 2283 struct IfWeakMember; 2284 2285 template<typename T> 2286 struct IfWeakMember { 2287 template<typename U> 2288 static bool isDead(Visitor*, const U&) { return false; } 2289 }; 2290 2291 template<typename T> 2292 struct IfWeakMember<WeakMember<T> > { 2293 static bool isDead(Visitor* visitor, const WeakMember<T>& t) { return !visitor->isAlive(t.get()); } 2294 }; 2295 2296 #if COMPILER(CLANG) 2297 // Clang does not export the symbols that we have explicitly asked it 2298 // to export. This forces it to export all the methods from ThreadHeap. 2299 template<> void ThreadHeap<FinalizedHeapObjectHeader>::addPageToHeap(const GCInfo*); 2300 template<> void ThreadHeap<HeapObjectHeader>::addPageToHeap(const GCInfo*); 2301 extern template class PLATFORM_EXPORT ThreadHeap<FinalizedHeapObjectHeader>; 2302 extern template class PLATFORM_EXPORT ThreadHeap<HeapObjectHeader>; 2303 #endif 2304 2305 } 2306 2307 #endif // Heap_h 2308