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

Side by Side Diff: Source/platform/heap/Heap.h

Issue 1120893003: Oilpan: Put all TraceTraits into TraceTraits.h (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/platform/heap/Handle.h ('k') | Source/platform/heap/InlinedGlobalMarkingVisitor.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 1274 matching lines...) Expand 10 before | Expand all | Expand 10 after
1285 // TODO(haraken): We don't support reallocate() for finalizable objects. 1285 // TODO(haraken): We don't support reallocate() for finalizable objects.
1286 ASSERT(!Heap::gcInfo(previousHeader->gcInfoIndex())->hasFinalizer()); 1286 ASSERT(!Heap::gcInfo(previousHeader->gcInfoIndex())->hasFinalizer());
1287 ASSERT(previousHeader->gcInfoIndex() == GCInfoTrait<T>::index()); 1287 ASSERT(previousHeader->gcInfoIndex() == GCInfoTrait<T>::index());
1288 size_t copySize = previousHeader->payloadSize(); 1288 size_t copySize = previousHeader->payloadSize();
1289 if (copySize > size) 1289 if (copySize > size)
1290 copySize = size; 1290 copySize = size;
1291 memcpy(address, previous, copySize); 1291 memcpy(address, previous, copySize);
1292 return address; 1292 return address;
1293 } 1293 }
1294 1294
1295 template<bool needsTracing, WTF::WeakHandlingFlag weakHandlingFlag, WTF::ShouldW eakPointersBeMarkedStrongly strongify, typename T, typename Traits> struct Colle ctionBackingTraceTrait;
1296 template<typename T, typename Traits = WTF::VectorTraits<T>> class HeapVectorBac king { 1295 template<typename T, typename Traits = WTF::VectorTraits<T>> class HeapVectorBac king {
1297 public: 1296 public:
1298 static void finalize(void* pointer); 1297 static void finalize(void* pointer);
1299 void finalizeGarbageCollectedObject() { finalize(this); } 1298 void finalizeGarbageCollectedObject() { finalize(this); }
1300 }; 1299 };
1300
1301 template<typename T, typename Traits>
1302 void HeapVectorBacking<T, Traits>::finalize(void* pointer)
1303 {
1304 static_assert(Traits::needsDestruction, "Only vector buffers with items requ iring destruction should be finalized");
1305 // See the comment in HeapVectorBacking::trace.
1306 static_assert(Traits::canInitializeWithMemset || WTF::IsPolymorphic<T>::valu e, "HeapVectorBacking doesn't support objects that cannot be initialized with me mset or don't have a vtable");
1307
1308 ASSERT(!WTF::IsTriviallyDestructible<T>::value);
1309 HeapObjectHeader* header = HeapObjectHeader::fromPayload(pointer);
1310 // Use the payload size as recorded by the heap to determine how many
1311 // elements to finalize.
1312 size_t length = header->payloadSize() / sizeof(T);
1313 T* buffer = reinterpret_cast<T*>(pointer);
1314 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER
1315 // As commented above, HeapVectorBacking calls finalizers for unused slots
1316 // (which are already zeroed out).
1317 ANNOTATE_CHANGE_SIZE(buffer, length, 0, length);
1318 #endif
1319 if (WTF::IsPolymorphic<T>::value) {
1320 for (unsigned i = 0; i < length; ++i) {
1321 if (blink::vTableInitialized(&buffer[i]))
1322 buffer[i].~T();
1323 }
1324 } else {
1325 for (unsigned i = 0; i < length; ++i) {
1326 buffer[i].~T();
1327 }
1328 }
1329 }
1330
1301 template<typename Table> class HeapHashTableBacking { 1331 template<typename Table> class HeapHashTableBacking {
1302 public: 1332 public:
1303 static void finalize(void* pointer); 1333 static void finalize(void* pointer);
1304 void finalizeGarbageCollectedObject() { finalize(this); } 1334 void finalizeGarbageCollectedObject() { finalize(this); }
1305 }; 1335 };
1306 1336
1337 template<typename Table>
1338 void HeapHashTableBacking<Table>::finalize(void* pointer)
1339 {
1340 using Value = typename Table::ValueType;
1341 ASSERT(!WTF::IsTriviallyDestructible<Value>::value);
1342 HeapObjectHeader* header = HeapObjectHeader::fromPayload(pointer);
1343 // Use the payload size as recorded by the heap to determine how many
1344 // elements to finalize.
1345 size_t length = header->payloadSize() / sizeof(Value);
1346 Value* table = reinterpret_cast<Value*>(pointer);
1347 for (unsigned i = 0; i < length; ++i) {
1348 if (!Table::isEmptyOrDeletedBucket(table[i]))
1349 table[i].~Value();
1350 }
1351 }
1352
1307 class HeapAllocatorQuantizer { 1353 class HeapAllocatorQuantizer {
1308 public: 1354 public:
1309 template<typename T> 1355 template<typename T>
1310 static size_t quantizedSize(size_t count) 1356 static size_t quantizedSize(size_t count)
1311 { 1357 {
1312 RELEASE_ASSERT(count <= kMaxUnquantizedAllocation / sizeof(T)); 1358 RELEASE_ASSERT(count <= kMaxUnquantizedAllocation / sizeof(T));
1313 return Heap::roundedAllocationSize(count * sizeof(T)); 1359 return Heap::roundedAllocationSize(count * sizeof(T));
1314 } 1360 }
1315 static const size_t kMaxUnquantizedAllocation = maxHeapObjectSize; 1361 static const size_t kMaxUnquantizedAllocation = maxHeapObjectSize;
1316 }; 1362 };
1317 1363
1364 // CollectionBackingTraceTrait. Do nothing for things in collections that don't
1365 // need tracing, or call TraceInCollectionTrait for those that do.
1366
1367 template<bool needsTracing, WTF::WeakHandlingFlag weakHandlingFlag, WTF::ShouldW eakPointersBeMarkedStrongly strongify, typename T, typename Traits> struct Colle ctionBackingTraceTrait;
1368
1369 // Specialization for things that don't need marking and have no weak pointers.
1370 // We do nothing, even if WTF::WeakPointersActStrong.
1371 template<WTF::ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits>
1372 struct CollectionBackingTraceTrait<false, WTF::NoWeakHandlingInCollections, stro ngify, T, Traits> {
1373 template<typename VisitorDispatcher>
1374 static bool trace(VisitorDispatcher, T&) { return false; }
1375 };
1376
1377 template<typename T>
1378 static void verifyGarbageCollectedIfMember(T*)
1379 {
1380 }
1381
1382 template<typename T>
1383 static void verifyGarbageCollectedIfMember(Member<T>* t)
1384 {
1385 STATIC_ASSERT_IS_GARBAGE_COLLECTED(T, "non garbage collected object in membe r");
1386 }
1387
1388 // Specialization for things that either need marking or have weak pointers or
1389 // both.
1390 template<bool needsTracing, WTF::WeakHandlingFlag weakHandlingFlag, WTF::ShouldW eakPointersBeMarkedStrongly strongify, typename T, typename Traits>
1391 struct CollectionBackingTraceTrait {
1392 template<typename VisitorDispatcher>
1393 static bool trace(VisitorDispatcher visitor, T&t)
1394 {
1395 verifyGarbageCollectedIfMember(reinterpret_cast<T*>(0));
1396 return WTF::TraceInCollectionTrait<weakHandlingFlag, strongify, T, Trait s>::trace(visitor, t);
1397 }
1398 };
1399
1400 template<typename T> struct WeakHandlingHashTraits : WTF::SimpleClassHashTraits< T> {
1401 // We want to treat the object as a weak object in the sense that it can
1402 // disappear from hash sets and hash maps.
1403 static const WTF::WeakHandlingFlag weakHandlingFlag = WTF::WeakHandlingInCol lections;
1404 // Normally whether or not an object needs tracing is inferred
1405 // automatically from the presence of the trace method, but we don't
1406 // necessarily have a trace method, and we may not need one because T
1407 // can perhaps only be allocated inside collections, never as independent
1408 // objects. Explicitly mark this as needing tracing and it will be traced
1409 // in collections using the traceInCollection method, which it must have.
1410 template<typename U = void> struct NeedsTracingLazily {
1411 static const bool value = true;
1412 };
1413 // The traceInCollection method traces differently depending on whether we
1414 // are strongifying the trace operation. We strongify the trace operation
1415 // when there are active iterators on the object. In this case all
1416 // WeakMembers are marked like strong members so that elements do not
1417 // suddenly disappear during iteration. Returns true if weak pointers to
1418 // dead objects were found: In this case any strong pointers were not yet
1419 // traced and the entry should be removed from the collection.
1420 template<typename VisitorDispatcher>
1421 static bool traceInCollection(VisitorDispatcher visitor, T& t, WTF::ShouldWe akPointersBeMarkedStrongly strongify)
1422 {
1423 return t.traceInCollection(visitor, strongify);
1424 }
1425 };
1426
1318 // This is a static-only class used as a trait on collections to make them heap 1427 // This is a static-only class used as a trait on collections to make them heap
1319 // allocated. However see also HeapListHashSetAllocator. 1428 // allocated. However see also HeapListHashSetAllocator.
1320 class HeapAllocator { 1429 class HeapAllocator {
1321 public: 1430 public:
1322 using Quantizer = HeapAllocatorQuantizer; 1431 using Quantizer = HeapAllocatorQuantizer;
1323 using Visitor = blink::Visitor; 1432 using Visitor = blink::Visitor;
1324 static const bool isGarbageCollected = true; 1433 static const bool isGarbageCollected = true;
1325 1434
1326 template <typename T> 1435 template <typename T>
1327 static T* allocateVectorBacking(size_t size) 1436 static T* allocateVectorBacking(size_t size)
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
1673 inline void swap(HeapHashMap<T, U, V, W, X>& a, HeapHashMap<T, U, V, W, X>& b) { a.swap(b); } 1782 inline void swap(HeapHashMap<T, U, V, W, X>& a, HeapHashMap<T, U, V, W, X>& b) { a.swap(b); }
1674 template<typename T, size_t i, typename U> 1783 template<typename T, size_t i, typename U>
1675 inline void swap(HeapListHashSet<T, i, U>& a, HeapListHashSet<T, i, U>& b) { a.s wap(b); } 1784 inline void swap(HeapListHashSet<T, i, U>& a, HeapListHashSet<T, i, U>& b) { a.s wap(b); }
1676 template<typename T, typename U, typename V> 1785 template<typename T, typename U, typename V>
1677 inline void swap(HeapLinkedHashSet<T, U, V>& a, HeapLinkedHashSet<T, U, V>& b) { a.swap(b); } 1786 inline void swap(HeapLinkedHashSet<T, U, V>& a, HeapLinkedHashSet<T, U, V>& b) { a.swap(b); }
1678 template<typename T, typename U, typename V> 1787 template<typename T, typename U, typename V>
1679 inline void swap(HeapHashCountedSet<T, U, V>& a, HeapHashCountedSet<T, U, V>& b) { a.swap(b); } 1788 inline void swap(HeapHashCountedSet<T, U, V>& a, HeapHashCountedSet<T, U, V>& b) { a.swap(b); }
1680 1789
1681 } // namespace blink 1790 } // namespace blink
1682 1791
1683 namespace WTF {
1684
1685 // Catch-all for types that have a way to trace that don't have special
1686 // handling for weakness in collections. This means that if this type
1687 // contains WeakMember fields, they will simply be zeroed, but the entry
1688 // will not be removed from the collection. This always happens for
1689 // things in vectors, which don't currently support special handling of
1690 // weak elements.
1691 template<ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Trai ts>
1692 struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, T, Traits> {
1693 template<typename VisitorDispatcher>
1694 static bool trace(VisitorDispatcher visitor, T& t)
1695 {
1696 blink::TraceTrait<T>::trace(visitor, &t);
1697 return false;
1698 }
1699 };
1700
1701 template<ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Trai ts>
1702 struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, blink::Mem ber<T>, Traits> {
1703 template<typename VisitorDispatcher>
1704 static bool trace(VisitorDispatcher visitor, blink::Member<T>& t)
1705 {
1706 blink::TraceTrait<T>::mark(visitor, const_cast<typename RemoveConst<T>:: Type*>(t.get()));
1707 return false;
1708 }
1709 };
1710
1711 // Catch-all for things that have HashTrait support for tracing with weakness.
1712 template<ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Trai ts>
1713 struct TraceInCollectionTrait<WeakHandlingInCollections, strongify, T, Traits> {
1714 template<typename VisitorDispatcher>
1715 static bool trace(VisitorDispatcher visitor, T& t)
1716 {
1717 return Traits::traceInCollection(visitor, t, strongify);
1718 }
1719 };
1720
1721 // Vector backing that needs marking. We don't support weak members in vectors.
1722 template<ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Trai ts>
1723 struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, blink::Hea pVectorBacking<T, Traits>, void> {
1724 template<typename VisitorDispatcher>
1725 static bool trace(VisitorDispatcher visitor, void* self)
1726 {
1727 // HeapVectorBacking does not know the exact size of the vector
1728 // and just knows the capacity of the vector. Due to the constraint,
1729 // HeapVectorBacking can support only the following objects:
1730 //
1731 // - An object that has a vtable. In this case, HeapVectorBacking
1732 // traces only slots that are not zeroed out. This is because if
1733 // the object has a vtable, the zeroed slot means that it is
1734 // an unused slot (Remember that the unused slots are guaranteed
1735 // to be zeroed out by VectorUnusedSlotClearer).
1736 //
1737 // - An object that can be initialized with memset. In this case,
1738 // HeapVectorBacking traces all slots including unused slots.
1739 // This is fine because the fact that the object can be initialized
1740 // with memset indicates that it is safe to treat the zerod slot
1741 // as a valid object.
1742 static_assert(!ShouldBeTraced<Traits>::value || Traits::canInitializeWit hMemset || WTF::IsPolymorphic<T>::value, "HeapVectorBacking doesn't support obje cts that cannot be initialized with memset.");
1743
1744 T* array = reinterpret_cast<T*>(self);
1745 blink::HeapObjectHeader* header = blink::HeapObjectHeader::fromPayload(s elf);
1746 // Use the payload size as recorded by the heap to determine how many
1747 // elements to trace.
1748 size_t length = header->payloadSize() / sizeof(T);
1749 if (WTF::IsPolymorphic<T>::value) {
1750 for (size_t i = 0; i < length; ++i) {
1751 if (blink::vTableInitialized(&array[i]))
1752 blink::CollectionBackingTraceTrait<ShouldBeTraced<Traits>::v alue, Traits::weakHandlingFlag, WeakPointersActStrong, T, Traits>::trace(visitor , array[i]);
1753 }
1754 } else {
1755 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER
1756 // As commented above, HeapVectorBacking can trace unused slots
1757 // (which are already zeroed out).
1758 ANNOTATE_CHANGE_SIZE(array, length, 0, length);
1759 #endif
1760 for (size_t i = 0; i < length; ++i)
1761 blink::CollectionBackingTraceTrait<ShouldBeTraced<Traits>::value , Traits::weakHandlingFlag, WeakPointersActStrong, T, Traits>::trace(visitor, ar ray[i]);
1762 }
1763 return false;
1764 }
1765 };
1766
1767 // Almost all hash table backings are visited with this specialization.
1768 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Table>
1769 struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, blink::Hea pHashTableBacking<Table>, void> {
1770 using Value = typename Table::ValueType;
1771 using Traits = typename Table::ValueTraits;
1772
1773 template<typename VisitorDispatcher>
1774 static bool trace(VisitorDispatcher visitor, void* self)
1775 {
1776 Value* array = reinterpret_cast<Value*>(self);
1777 blink::HeapObjectHeader* header = blink::HeapObjectHeader::fromPayload(s elf);
1778 size_t length = header->payloadSize() / sizeof(Value);
1779 for (size_t i = 0; i < length; ++i) {
1780 if (!HashTableHelper<Value, typename Table::ExtractorType, typename Table::KeyTraitsType>::isEmptyOrDeletedBucket(array[i]))
1781 blink::CollectionBackingTraceTrait<ShouldBeTraced<Traits>::value , Traits::weakHandlingFlag, strongify, Value, Traits>::trace(visitor, array[i]);
1782 }
1783 return false;
1784 }
1785 };
1786
1787 // This specialization of TraceInCollectionTrait is for the backing of
1788 // HeapListHashSet. This is for the case that we find a reference to the
1789 // backing from the stack. That probably means we have a GC while we are in a
1790 // ListHashSet method since normal API use does not put pointers to the backing
1791 // on the stack.
1792 template<ShouldWeakPointersBeMarkedStrongly strongify, typename NodeContents, si ze_t inlineCapacity, typename T, typename U, typename V, typename W, typename X, typename Y>
1793 struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, blink::Hea pHashTableBacking<HashTable<ListHashSetNode<NodeContents, blink::HeapListHashSet Allocator<T, inlineCapacity>>*, U, V, W, X, Y, blink::HeapAllocator>>, void> {
1794 using Node = ListHashSetNode<NodeContents, blink::HeapListHashSetAllocator<T , inlineCapacity>>;
1795 using Table = HashTable<Node*, U, V, W, X, Y, blink::HeapAllocator>;
1796
1797 template<typename VisitorDispatcher>
1798 static bool trace(VisitorDispatcher visitor, void* self)
1799 {
1800 Node** array = reinterpret_cast<Node**>(self);
1801 blink::HeapObjectHeader* header = blink::HeapObjectHeader::fromPayload(s elf);
1802 size_t length = header->payloadSize() / sizeof(Node*);
1803 for (size_t i = 0; i < length; ++i) {
1804 if (!HashTableHelper<Node*, typename Table::ExtractorType, typename Table::KeyTraitsType>::isEmptyOrDeletedBucket(array[i])) {
1805 traceListHashSetValue(visitor, array[i]->m_value);
1806 // Just mark the node without tracing because we already traced
1807 // the contents, and there is no need to trace the next and
1808 // prev fields since iterating over the hash table backing will
1809 // find the whole chain.
1810 visitor->markNoTracing(array[i]);
1811 }
1812 }
1813 return false;
1814 }
1815 };
1816
1817 // Key value pairs, as used in HashMap. To disambiguate template choice we have
1818 // to have two versions, first the one with no special weak handling, then the
1819 // one with weak handling.
1820 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Key, typename Va lue, typename Traits>
1821 struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, KeyValuePa ir<Key, Value>, Traits> {
1822 template<typename VisitorDispatcher>
1823 static bool trace(VisitorDispatcher visitor, KeyValuePair<Key, Value>& self)
1824 {
1825 ASSERT(ShouldBeTraced<Traits>::value);
1826 blink::CollectionBackingTraceTrait<ShouldBeTraced<typename Traits::KeyTr aits>::value, NoWeakHandlingInCollections, strongify, Key, typename Traits::KeyT raits>::trace(visitor, self.key);
1827 blink::CollectionBackingTraceTrait<ShouldBeTraced<typename Traits::Value Traits>::value, NoWeakHandlingInCollections, strongify, Value, typename Traits:: ValueTraits>::trace(visitor, self.value);
1828 return false;
1829 }
1830 };
1831
1832 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Key, typename Va lue, typename Traits>
1833 struct TraceInCollectionTrait<WeakHandlingInCollections, strongify, KeyValuePair <Key, Value>, Traits> {
1834 template<typename VisitorDispatcher>
1835 static bool trace(VisitorDispatcher visitor, KeyValuePair<Key, Value>& self)
1836 {
1837 // This is the core of the ephemeron-like functionality. If there is
1838 // weakness on the key side then we first check whether there are
1839 // dead weak pointers on that side, and if there are we don't mark the
1840 // value side (yet). Conversely if there is weakness on the value side
1841 // we check that first and don't mark the key side yet if we find dead
1842 // weak pointers.
1843 // Corner case: If there is weakness on both the key and value side,
1844 // and there are also strong pointers on the both sides then we could
1845 // unexpectedly leak. The scenario is that the weak pointer on the key
1846 // side is alive, which causes the strong pointer on the key side to be
1847 // marked. If that then results in the object pointed to by the weak
1848 // pointer on the value side being marked live, then the whole
1849 // key-value entry is leaked. To avoid unexpected leaking, we disallow
1850 // this case, but if you run into this assert, please reach out to Blink
1851 // reviewers, and we may relax it.
1852 const bool keyIsWeak = Traits::KeyTraits::weakHandlingFlag == WeakHandli ngInCollections;
1853 const bool valueIsWeak = Traits::ValueTraits::weakHandlingFlag == WeakHa ndlingInCollections;
1854 const bool keyHasStrongRefs = ShouldBeTraced<typename Traits::KeyTraits> ::value;
1855 const bool valueHasStrongRefs = ShouldBeTraced<typename Traits::ValueTra its>::value;
1856 static_assert(!keyIsWeak || !valueIsWeak || !keyHasStrongRefs || !valueH asStrongRefs, "this configuration is disallowed to avoid unexpected leaks");
1857 if ((valueIsWeak && !keyIsWeak) || (valueIsWeak && keyIsWeak && !valueHa sStrongRefs)) {
1858 // Check value first.
1859 bool deadWeakObjectsFoundOnValueSide = blink::CollectionBackingTrace Trait<ShouldBeTraced<typename Traits::ValueTraits>::value, Traits::ValueTraits:: weakHandlingFlag, strongify, Value, typename Traits::ValueTraits>::trace(visitor , self.value);
1860 if (deadWeakObjectsFoundOnValueSide)
1861 return true;
1862 return blink::CollectionBackingTraceTrait<ShouldBeTraced<typename Tr aits::KeyTraits>::value, Traits::KeyTraits::weakHandlingFlag, strongify, Key, ty pename Traits::KeyTraits>::trace(visitor, self.key);
1863 }
1864 // Check key first.
1865 bool deadWeakObjectsFoundOnKeySide = blink::CollectionBackingTraceTrait< ShouldBeTraced<typename Traits::KeyTraits>::value, Traits::KeyTraits::weakHandli ngFlag, strongify, Key, typename Traits::KeyTraits>::trace(visitor, self.key);
1866 if (deadWeakObjectsFoundOnKeySide)
1867 return true;
1868 return blink::CollectionBackingTraceTrait<ShouldBeTraced<typename Traits ::ValueTraits>::value, Traits::ValueTraits::weakHandlingFlag, strongify, Value, typename Traits::ValueTraits>::trace(visitor, self.value);
1869 }
1870 };
1871
1872 // Nodes used by LinkedHashSet. Again we need two versions to disambiguate the
1873 // template.
1874 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Value, typename Allocator, typename Traits>
1875 struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, LinkedHash SetNode<Value, Allocator>, Traits> {
1876 template<typename VisitorDispatcher>
1877 static bool trace(VisitorDispatcher visitor, LinkedHashSetNode<Value, Alloca tor>& self)
1878 {
1879 ASSERT(ShouldBeTraced<Traits>::value);
1880 return TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, Va lue, typename Traits::ValueTraits>::trace(visitor, self.m_value);
1881 }
1882 };
1883
1884 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Value, typename Allocator, typename Traits>
1885 struct TraceInCollectionTrait<WeakHandlingInCollections, strongify, LinkedHashSe tNode<Value, Allocator>, Traits> {
1886 template<typename VisitorDispatcher>
1887 static bool trace(VisitorDispatcher visitor, LinkedHashSetNode<Value, Alloca tor>& self)
1888 {
1889 return TraceInCollectionTrait<WeakHandlingInCollections, strongify, Valu e, typename Traits::ValueTraits>::trace(visitor, self.m_value);
1890 }
1891 };
1892
1893 // ListHashSetNode pointers (a ListHashSet is implemented as a hash table of
1894 // these pointers).
1895 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Value, size_t in lineCapacity, typename Traits>
1896 struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, ListHashSe tNode<Value, blink::HeapListHashSetAllocator<Value, inlineCapacity>>*, Traits> {
1897 using Node = ListHashSetNode<Value, blink::HeapListHashSetAllocator<Value, i nlineCapacity>>;
1898
1899 template<typename VisitorDispatcher>
1900 static bool trace(VisitorDispatcher visitor, Node* node)
1901 {
1902 traceListHashSetValue(visitor, node->m_value);
1903 // Just mark the node without tracing because we already traced the
1904 // contents, and there is no need to trace the next and prev fields
1905 // since iterating over the hash table backing will find the whole
1906 // chain.
1907 visitor->markNoTracing(node);
1908 return false;
1909 }
1910 };
1911
1912 } // namespace WTF
1913
1914 namespace blink {
1915
1916 // CollectionBackingTraceTrait. Do nothing for things in collections that don't
1917 // need tracing, or call TraceInCollectionTrait for those that do.
1918
1919 // Specialization for things that don't need marking and have no weak pointers.
1920 // We do nothing, even if WTF::WeakPointersActStrong.
1921 template<WTF::ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits>
1922 struct CollectionBackingTraceTrait<false, WTF::NoWeakHandlingInCollections, stro ngify, T, Traits> {
1923 template<typename VisitorDispatcher>
1924 static bool trace(VisitorDispatcher, T&) { return false; }
1925 };
1926
1927 template<typename T>
1928 static void verifyGarbageCollectedIfMember(T*)
1929 {
1930 }
1931
1932 template<typename T>
1933 static void verifyGarbageCollectedIfMember(Member<T>* t)
1934 {
1935 STATIC_ASSERT_IS_GARBAGE_COLLECTED(T, "non garbage collected object in membe r");
1936 }
1937
1938 // Specialization for things that either need marking or have weak pointers or
1939 // both.
1940 template<bool needsTracing, WTF::WeakHandlingFlag weakHandlingFlag, WTF::ShouldW eakPointersBeMarkedStrongly strongify, typename T, typename Traits>
1941 struct CollectionBackingTraceTrait {
1942 template<typename VisitorDispatcher>
1943 static bool trace(VisitorDispatcher visitor, T&t)
1944 {
1945 verifyGarbageCollectedIfMember(reinterpret_cast<T*>(0));
1946 return WTF::TraceInCollectionTrait<weakHandlingFlag, strongify, T, Trait s>::trace(visitor, t);
1947 }
1948 };
1949
1950 template<typename T> struct WeakHandlingHashTraits : WTF::SimpleClassHashTraits< T> {
1951 // We want to treat the object as a weak object in the sense that it can
1952 // disappear from hash sets and hash maps.
1953 static const WTF::WeakHandlingFlag weakHandlingFlag = WTF::WeakHandlingInCol lections;
1954 // Normally whether or not an object needs tracing is inferred
1955 // automatically from the presence of the trace method, but we don't
1956 // necessarily have a trace method, and we may not need one because T
1957 // can perhaps only be allocated inside collections, never as independent
1958 // objects. Explicitly mark this as needing tracing and it will be traced
1959 // in collections using the traceInCollection method, which it must have.
1960 template<typename U = void> struct NeedsTracingLazily {
1961 static const bool value = true;
1962 };
1963 // The traceInCollection method traces differently depending on whether we
1964 // are strongifying the trace operation. We strongify the trace operation
1965 // when there are active iterators on the object. In this case all
1966 // WeakMembers are marked like strong members so that elements do not
1967 // suddenly disappear during iteration. Returns true if weak pointers to
1968 // dead objects were found: In this case any strong pointers were not yet
1969 // traced and the entry should be removed from the collection.
1970 template<typename VisitorDispatcher>
1971 static bool traceInCollection(VisitorDispatcher visitor, T& t, WTF::ShouldWe akPointersBeMarkedStrongly strongify)
1972 {
1973 return t.traceInCollection(visitor, strongify);
1974 }
1975 };
1976
1977 template<typename T, typename Traits>
1978 struct TraceTrait<HeapVectorBacking<T, Traits>> {
1979 using Backing = HeapVectorBacking<T, Traits>;
1980
1981 template<typename VisitorDispatcher>
1982 static void trace(VisitorDispatcher visitor, void* self)
1983 {
1984 static_assert(!WTF::IsWeak<T>::value, "weakness in HeapVectors and Deque s are not supported");
1985 if (WTF::ShouldBeTraced<Traits>::value)
1986 WTF::TraceInCollectionTrait<WTF::NoWeakHandlingInCollections, WTF::W eakPointersActWeak, HeapVectorBacking<T, Traits>, void>::trace(visitor, self);
1987 }
1988
1989 template<typename VisitorDispatcher>
1990 static void mark(VisitorDispatcher visitor, const Backing* backing)
1991 {
1992 visitor->mark(backing, &trace);
1993 }
1994 static void checkGCInfo(Visitor* visitor, const Backing* backing)
1995 {
1996 #if ENABLE(ASSERT)
1997 assertObjectHasGCInfo(const_cast<Backing*>(backing), GCInfoTrait<Backing >::index());
1998 #endif
1999 }
2000 };
2001
2002 // The trace trait for the heap hashtable backing is used when we find a
2003 // direct pointer to the backing from the conservative stack scanner. This
2004 // normally indicates that there is an ongoing iteration over the table, and so
2005 // we disable weak processing of table entries. When the backing is found
2006 // through the owning hash table we mark differently, in order to do weak
2007 // processing.
2008 template<typename Table>
2009 struct TraceTrait<HeapHashTableBacking<Table>> {
2010 using Backing = HeapHashTableBacking<Table>;
2011 using Traits = typename Table::ValueTraits;
2012
2013 template<typename VisitorDispatcher>
2014 static void trace(VisitorDispatcher visitor, void* self)
2015 {
2016 if (WTF::ShouldBeTraced<Traits>::value || Traits::weakHandlingFlag == WT F::WeakHandlingInCollections)
2017 WTF::TraceInCollectionTrait<WTF::NoWeakHandlingInCollections, WTF::W eakPointersActStrong, Backing, void>::trace(visitor, self);
2018 }
2019
2020 template<typename VisitorDispatcher>
2021 static void mark(VisitorDispatcher visitor, const Backing* backing)
2022 {
2023 if (WTF::ShouldBeTraced<Traits>::value || Traits::weakHandlingFlag == WT F::WeakHandlingInCollections)
2024 visitor->mark(backing, &trace);
2025 else
2026 visitor->markNoTracing(backing); // If we know the trace function wi ll do nothing there is no need to call it.
2027 }
2028 static void checkGCInfo(Visitor* visitor, const Backing* backing)
2029 {
2030 #if ENABLE(ASSERT)
2031 assertObjectHasGCInfo(const_cast<Backing*>(backing), GCInfoTrait<Backing >::index());
2032 #endif
2033 }
2034 };
2035
2036 template<typename T, typename Traits>
2037 void HeapVectorBacking<T, Traits>::finalize(void* pointer)
2038 {
2039 static_assert(Traits::needsDestruction, "Only vector buffers with items requ iring destruction should be finalized");
2040 // See the comment in HeapVectorBacking::trace.
2041 static_assert(Traits::canInitializeWithMemset || WTF::IsPolymorphic<T>::valu e, "HeapVectorBacking doesn't support objects that cannot be initialized with me mset or don't have a vtable");
2042
2043 ASSERT(!WTF::IsTriviallyDestructible<T>::value);
2044 HeapObjectHeader* header = HeapObjectHeader::fromPayload(pointer);
2045 // Use the payload size as recorded by the heap to determine how many
2046 // elements to finalize.
2047 size_t length = header->payloadSize() / sizeof(T);
2048 T* buffer = reinterpret_cast<T*>(pointer);
2049 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER
2050 // As commented above, HeapVectorBacking calls finalizers for unused slots
2051 // (which are already zeroed out).
2052 ANNOTATE_CHANGE_SIZE(buffer, length, 0, length);
2053 #endif
2054 if (WTF::IsPolymorphic<T>::value) {
2055 for (unsigned i = 0; i < length; ++i) {
2056 if (blink::vTableInitialized(&buffer[i]))
2057 buffer[i].~T();
2058 }
2059 } else {
2060 for (unsigned i = 0; i < length; ++i) {
2061 buffer[i].~T();
2062 }
2063 }
2064 }
2065
2066 template<typename Table>
2067 void HeapHashTableBacking<Table>::finalize(void* pointer)
2068 {
2069 using Value = typename Table::ValueType;
2070 ASSERT(!WTF::IsTriviallyDestructible<Value>::value);
2071 HeapObjectHeader* header = HeapObjectHeader::fromPayload(pointer);
2072 // Use the payload size as recorded by the heap to determine how many
2073 // elements to finalize.
2074 size_t length = header->payloadSize() / sizeof(Value);
2075 Value* table = reinterpret_cast<Value*>(pointer);
2076 for (unsigned i = 0; i < length; ++i) {
2077 if (!Table::isEmptyOrDeletedBucket(table[i]))
2078 table[i].~Value();
2079 }
2080 }
2081
2082 } // namespace blink
2083
2084 #endif // Heap_h 1792 #endif // Heap_h
OLDNEW
« no previous file with comments | « Source/platform/heap/Handle.h ('k') | Source/platform/heap/InlinedGlobalMarkingVisitor.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698