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

Unified Diff: Source/platform/heap/TraceTraits.h

Issue 1120893003: Oilpan: Put all TraceTraits into TraceTraits.h (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/platform/heap/InlinedGlobalMarkingVisitor.h ('k') | Source/platform/heap/Visitor.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/platform/heap/TraceTraits.h
diff --git a/Source/platform/heap/TraceTraits.h b/Source/platform/heap/TraceTraits.h
new file mode 100644
index 0000000000000000000000000000000000000000..a463dd925857759346f065bac41b2bc2d5fa755f
--- /dev/null
+++ b/Source/platform/heap/TraceTraits.h
@@ -0,0 +1,558 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TraceTraits_h
+#define TraceTraits_h
+
+#include "platform/heap/GCInfo.h"
+#include "platform/heap/Heap.h"
+#include "platform/heap/Visitor.h"
+#include "wtf/Assertions.h"
+#include "wtf/Deque.h"
+#include "wtf/HashCountedSet.h"
+#include "wtf/HashMap.h"
+#include "wtf/HashSet.h"
+#include "wtf/HashTable.h"
+#include "wtf/LinkedHashSet.h"
+#include "wtf/ListHashSet.h"
+#include "wtf/TypeTraits.h"
+#include "wtf/Vector.h"
+
+namespace blink {
+
+template<typename T> class CrossThreadPersistent;
+template<typename T> struct GCInfoTrait;
+class HeapObjectHeader;
+template<typename T> class Member;
+template<typename T, bool> class NeedsAdjustAndMark;
+template<typename T> class TraceTrait;
+template<typename T> class WeakMember;
+
+template<typename T, bool = NeedsAdjustAndMark<T>::value> class DefaultTraceTrait;
+
+template<typename T>
+class DefaultTraceTrait<T, false> {
+public:
+ template<typename VisitorDispatcher>
+ static void mark(VisitorDispatcher visitor, const T* t)
+ {
+ // Default mark method of the trait just calls the two-argument mark
+ // method on the visitor. The second argument is the static trace method
+ // of the trait, which by default calls the instance method
+ // trace(Visitor*) on the object.
+ //
+ // If the trait allows it, invoke the trace callback right here on the
+ // not-yet-marked object.
+ if (TraceEagerlyTrait<T>::value) {
+ // Protect against too deep trace call chains, and the
+ // unbounded system stack usage they can bring about.
+ //
+ // Assert against deep stacks so as to flush them out,
+ // but test and appropriately handle them should they occur
+ // in release builds.
+ //
+ // ASan adds extra stack usage, so disable the assert when it is
+ // enabled so as to avoid testing against a much lower & too low,
+ // stack depth threshold.
+#if !defined(ADDRESS_SANITIZER)
+ ASSERT(StackFrameDepth::isSafeToRecurse());
+#endif
+ if (LIKELY(StackFrameDepth::isSafeToRecurse())) {
+ if (visitor->ensureMarked(t)) {
+ TraceTrait<T>::trace(visitor, const_cast<T*>(t));
+ }
+ return;
+ }
+ }
+ visitor->mark(const_cast<T*>(t), &TraceTrait<T>::trace);
+ }
+
+#if ENABLE(ASSERT)
+ static void checkGCInfo(const T* t)
+ {
+ assertObjectHasGCInfo(const_cast<T*>(t), GCInfoTrait<T>::index());
+ }
+#endif
+};
+
+template<typename T>
+class DefaultTraceTrait<T, true> {
+public:
+ template<typename VisitorDispatcher>
+ static void mark(VisitorDispatcher visitor, const T* self)
+ {
+ if (!self)
+ return;
+
+ // If you hit this ASSERT, it means that there is a dangling pointer
+ // from a live thread heap to a dead thread heap. We must eliminate
+ // the dangling pointer.
+ // Release builds don't have the ASSERT, but it is OK because
+ // release builds will crash at the following self->adjustAndMark
+ // because all the entries of the orphaned heaps are zeroed out and
+ // thus the item does not have a valid vtable.
+ ASSERT(!pageFromObject(self)->orphaned());
+ self->adjustAndMark(visitor);
+ }
+
+#if ENABLE(ASSERT)
+ static void checkGCInfo(const T*) { }
+#endif
+};
+
+template<typename T, bool needsTracing>
+struct TraceIfEnabled;
+
+template<typename T>
+struct TraceIfEnabled<T, false> {
+ template<typename VisitorDispatcher>
+ static void trace(VisitorDispatcher, T*) { }
+};
+
+template<typename T>
+struct TraceIfEnabled<T, true> {
+ template<typename VisitorDispatcher>
+ static void trace(VisitorDispatcher visitor, T* t)
+ {
+ visitor->trace(*t);
+ }
+};
+
+// The TraceTrait is used to specify how to mark an object pointer and
+// how to trace all of the pointers in the object.
+//
+// By default, the 'trace' method implemented on an object itself is
+// used to trace the pointers to other heap objects inside the object.
+//
+// However, the TraceTrait can be specialized to use a different
+// implementation. A common case where a TraceTrait specialization is
+// needed is when multiple inheritance leads to pointers that are not
+// to the start of the object in the Blink garbage-collected heap. In
+// that case the pointer has to be adjusted before marking.
+template<typename T>
+class TraceTrait {
+public:
+ static void trace(Visitor*, void* self);
+ static void trace(InlinedGlobalMarkingVisitor, void* self);
+
+ template<typename VisitorDispatcher>
+ static void mark(VisitorDispatcher visitor, const T* t)
+ {
+ DefaultTraceTrait<T>::mark(visitor, t);
+ }
+
+#if ENABLE(ASSERT)
+ static void checkGCInfo(const T* t)
+ {
+ DefaultTraceTrait<T>::checkGCInfo(t);
+ }
+#endif
+};
+
+template<typename T> class TraceTrait<const T> : public TraceTrait<T> { };
+
+template<typename T>
+void TraceTrait<T>::trace(Visitor* visitor, void* self)
+{
+ if (visitor->isGlobalMarkingVisitor()) {
+ // Switch to inlined global marking dispatch.
+ static_cast<T*>(self)->trace(InlinedGlobalMarkingVisitor(visitor));
+ } else {
+ static_cast<T*>(self)->trace(visitor);
+ }
+}
+
+template<typename T>
+void TraceTrait<T>::trace(InlinedGlobalMarkingVisitor visitor, void* self)
+{
+ static_cast<T*>(self)->trace(visitor);
+}
+
+template<typename T, typename Traits>
+struct TraceTrait<HeapVectorBacking<T, Traits>> {
+ using Backing = HeapVectorBacking<T, Traits>;
+
+ template<typename VisitorDispatcher>
+ static void trace(VisitorDispatcher visitor, void* self)
+ {
+ static_assert(!WTF::IsWeak<T>::value, "weakness in HeapVectors and Deques are not supported");
+ if (WTF::ShouldBeTraced<Traits>::value)
+ WTF::TraceInCollectionTrait<WTF::NoWeakHandlingInCollections, WTF::WeakPointersActWeak, HeapVectorBacking<T, Traits>, void>::trace(visitor, self);
+ }
+
+ template<typename VisitorDispatcher>
+ static void mark(VisitorDispatcher visitor, const Backing* backing)
+ {
+ visitor->mark(backing, &trace);
+ }
+ static void checkGCInfo(Visitor* visitor, const Backing* backing)
+ {
+#if ENABLE(ASSERT)
+ assertObjectHasGCInfo(const_cast<Backing*>(backing), GCInfoTrait<Backing>::index());
+#endif
+ }
+};
+
+// The trace trait for the heap hashtable backing is used when we find a
+// direct pointer to the backing from the conservative stack scanner. This
+// normally indicates that there is an ongoing iteration over the table, and so
+// we disable weak processing of table entries. When the backing is found
+// through the owning hash table we mark differently, in order to do weak
+// processing.
+template<typename Table>
+struct TraceTrait<HeapHashTableBacking<Table>> {
+ using Backing = HeapHashTableBacking<Table>;
+ using Traits = typename Table::ValueTraits;
+
+ template<typename VisitorDispatcher>
+ static void trace(VisitorDispatcher visitor, void* self)
+ {
+ if (WTF::ShouldBeTraced<Traits>::value || Traits::weakHandlingFlag == WTF::WeakHandlingInCollections)
+ WTF::TraceInCollectionTrait<WTF::NoWeakHandlingInCollections, WTF::WeakPointersActStrong, Backing, void>::trace(visitor, self);
+ }
+
+ template<typename VisitorDispatcher>
+ static void mark(VisitorDispatcher visitor, const Backing* backing)
+ {
+ if (WTF::ShouldBeTraced<Traits>::value || Traits::weakHandlingFlag == WTF::WeakHandlingInCollections)
+ visitor->mark(backing, &trace);
+ else
+ visitor->markNoTracing(backing); // If we know the trace function will do nothing there is no need to call it.
+ }
+ static void checkGCInfo(Visitor* visitor, const Backing* backing)
+ {
+#if ENABLE(ASSERT)
+ assertObjectHasGCInfo(const_cast<Backing*>(backing), GCInfoTrait<Backing>::index());
+#endif
+ }
+};
+
+// This trace trait for std::pair will null weak members if their referent is
+// collected. If you have a collection that contain weakness it does not remove
+// entries from the collection that contain nulled weak members.
+template<typename T, typename U>
+class TraceTrait<std::pair<T, U>> {
+public:
+ static const bool firstNeedsTracing = WTF::NeedsTracing<T>::value || WTF::IsWeak<T>::value;
+ static const bool secondNeedsTracing = WTF::NeedsTracing<U>::value || WTF::IsWeak<U>::value;
+ template<typename VisitorDispatcher>
+ static void trace(VisitorDispatcher visitor, std::pair<T, U>* pair)
+ {
+ TraceIfEnabled<T, firstNeedsTracing>::trace(visitor, &pair->first);
+ TraceIfEnabled<U, secondNeedsTracing>::trace(visitor, &pair->second);
+ }
+};
+
+// If eager tracing leads to excessively deep |trace()| call chains (and
+// the system stack usage that this brings), the marker implementation will
+// switch to using an explicit mark stack. Recursive and deep object graphs
+// are uncommon for Blink objects.
+//
+// A class type can opt out of eager tracing by declaring a TraceEagerlyTrait<>
+// specialization, mapping the trait's |value| to |false| (see the
+// WILL_NOT_BE_EAGERLY_TRACED_CLASS() macros below.) For Blink, this is done for
+// the small set of GCed classes that are directly recursive.
+//
+// The TraceEagerlyTrait<T> trait controls whether or not a class
+// (and its subclasses) should be eagerly traced or not.
+//
+// If |TraceEagerlyTrait<T>::value| is |true|, then the marker thread
+// should invoke |trace()| on not-yet-marked objects deriving from class T
+// right away, and not queue their trace callbacks on its marker stack,
+// which it will do if |value| is |false|.
+//
+// The trait can be declared to enable/disable eager tracing for a class T
+// and any of its subclasses, or just to the class T, but none of its
+// subclasses.
+//
+template<typename T>
+class TraceEagerlyTrait {
+public:
+ static const bool value = true;
+};
+
+// Disable eager tracing for TYPE, but not any of its subclasses.
+#define WILL_NOT_BE_EAGERLY_TRACED_CLASS(TYPE) \
+template<> \
+class TraceEagerlyTrait<TYPE> { \
+public: \
+ static const bool value = false; \
+}
+
+template<typename T>
+class TraceEagerlyTrait<Member<T>> {
+public:
+ static const bool value = TraceEagerlyTrait<T>::value;
+};
+
+template<typename T>
+class TraceEagerlyTrait<WeakMember<T>> {
+public:
+ static const bool value = TraceEagerlyTrait<T>::value;
+};
+
+template<typename T>
+class TraceEagerlyTrait<Persistent<T>> {
+public:
+ static const bool value = TraceEagerlyTrait<T>::value;
+};
+
+template<typename T>
+class TraceEagerlyTrait<CrossThreadPersistent<T>> {
+public:
+ static const bool value = TraceEagerlyTrait<T>::value;
+};
+
+template<typename ValueArg, size_t inlineCapacity> class HeapListHashSetAllocator;
+template<typename T, size_t inlineCapacity>
+class TraceEagerlyTrait<WTF::ListHashSetNode<T, HeapListHashSetAllocator<T, inlineCapacity>>> {
+public:
+ static const bool value = false;
+};
+
+template <typename T> struct RemoveHeapPointerWrapperTypes {
+ using Type = typename WTF::RemoveTemplate<typename WTF::RemoveTemplate<typename WTF::RemoveTemplate<T, Member>::Type, WeakMember>::Type, RawPtr>::Type;
+};
+
+// FIXME: Oilpan: TraceIfNeeded should be implemented ala:
+// NeedsTracing<T>::value || IsWeakMember<T>::value. It should not need to test
+// raw pointer types. To remove these tests, we may need support for
+// instantiating a template with a RawPtrOrMember'ish template.
+template<typename T>
+struct TraceIfNeeded : public TraceIfEnabled<T, WTF::NeedsTracing<T>::value || IsGarbageCollectedType<typename RemoveHeapPointerWrapperTypes<typename WTF::RemovePointer<T>::Type>::Type>::value> { };
+
+} // namespace blink
+
+namespace WTF {
+
+// Catch-all for types that have a way to trace that don't have special
+// handling for weakness in collections. This means that if this type
+// contains WeakMember fields, they will simply be zeroed, but the entry
+// will not be removed from the collection. This always happens for
+// things in vectors, which don't currently support special handling of
+// weak elements.
+template<ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits>
+struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, T, Traits> {
+ template<typename VisitorDispatcher>
+ static bool trace(VisitorDispatcher visitor, T& t)
+ {
+ blink::TraceTrait<T>::trace(visitor, &t);
+ return false;
+ }
+};
+
+template<ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits>
+struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, blink::Member<T>, Traits> {
+ template<typename VisitorDispatcher>
+ static bool trace(VisitorDispatcher visitor, blink::Member<T>& t)
+ {
+ blink::TraceTrait<T>::mark(visitor, const_cast<typename RemoveConst<T>::Type*>(t.get()));
+ return false;
+ }
+};
+
+// Catch-all for things that have HashTrait support for tracing with weakness.
+template<ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits>
+struct TraceInCollectionTrait<WeakHandlingInCollections, strongify, T, Traits> {
+ template<typename VisitorDispatcher>
+ static bool trace(VisitorDispatcher visitor, T& t)
+ {
+ return Traits::traceInCollection(visitor, t, strongify);
+ }
+};
+
+// Vector backing that needs marking. We don't support weak members in vectors.
+template<ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits>
+struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, blink::HeapVectorBacking<T, Traits>, void> {
+ template<typename VisitorDispatcher>
+ static bool trace(VisitorDispatcher visitor, void* self)
+ {
+ // HeapVectorBacking does not know the exact size of the vector
+ // and just knows the capacity of the vector. Due to the constraint,
+ // HeapVectorBacking can support only the following objects:
+ //
+ // - An object that has a vtable. In this case, HeapVectorBacking
+ // traces only slots that are not zeroed out. This is because if
+ // the object has a vtable, the zeroed slot means that it is
+ // an unused slot (Remember that the unused slots are guaranteed
+ // to be zeroed out by VectorUnusedSlotClearer).
+ //
+ // - An object that can be initialized with memset. In this case,
+ // HeapVectorBacking traces all slots including unused slots.
+ // This is fine because the fact that the object can be initialized
+ // with memset indicates that it is safe to treat the zerod slot
+ // as a valid object.
+ static_assert(!ShouldBeTraced<Traits>::value || Traits::canInitializeWithMemset || WTF::IsPolymorphic<T>::value, "HeapVectorBacking doesn't support objects that cannot be initialized with memset.");
+
+ T* array = reinterpret_cast<T*>(self);
+ blink::HeapObjectHeader* header = blink::HeapObjectHeader::fromPayload(self);
+ // Use the payload size as recorded by the heap to determine how many
+ // elements to trace.
+ size_t length = header->payloadSize() / sizeof(T);
+ if (WTF::IsPolymorphic<T>::value) {
+ for (size_t i = 0; i < length; ++i) {
+ if (blink::vTableInitialized(&array[i]))
+ blink::CollectionBackingTraceTrait<ShouldBeTraced<Traits>::value, Traits::weakHandlingFlag, WeakPointersActStrong, T, Traits>::trace(visitor, array[i]);
+ }
+ } else {
+#ifdef ANNOTATE_CONTIGUOUS_CONTAINER
+ // As commented above, HeapVectorBacking can trace unused slots
+ // (which are already zeroed out).
+ ANNOTATE_CHANGE_SIZE(array, length, 0, length);
+#endif
+ for (size_t i = 0; i < length; ++i)
+ blink::CollectionBackingTraceTrait<ShouldBeTraced<Traits>::value, Traits::weakHandlingFlag, WeakPointersActStrong, T, Traits>::trace(visitor, array[i]);
+ }
+ return false;
+ }
+};
+
+// Almost all hash table backings are visited with this specialization.
+template<ShouldWeakPointersBeMarkedStrongly strongify, typename Table>
+struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, blink::HeapHashTableBacking<Table>, void> {
+ using Value = typename Table::ValueType;
+ using Traits = typename Table::ValueTraits;
+
+ template<typename VisitorDispatcher>
+ static bool trace(VisitorDispatcher visitor, void* self)
+ {
+ Value* array = reinterpret_cast<Value*>(self);
+ blink::HeapObjectHeader* header = blink::HeapObjectHeader::fromPayload(self);
+ size_t length = header->payloadSize() / sizeof(Value);
+ for (size_t i = 0; i < length; ++i) {
+ if (!HashTableHelper<Value, typename Table::ExtractorType, typename Table::KeyTraitsType>::isEmptyOrDeletedBucket(array[i]))
+ blink::CollectionBackingTraceTrait<ShouldBeTraced<Traits>::value, Traits::weakHandlingFlag, strongify, Value, Traits>::trace(visitor, array[i]);
+ }
+ return false;
+ }
+};
+
+// This specialization of TraceInCollectionTrait is for the backing of
+// HeapListHashSet. This is for the case that we find a reference to the
+// backing from the stack. That probably means we have a GC while we are in a
+// ListHashSet method since normal API use does not put pointers to the backing
+// on the stack.
+template<ShouldWeakPointersBeMarkedStrongly strongify, typename NodeContents, size_t inlineCapacity, typename T, typename U, typename V, typename W, typename X, typename Y>
+struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, blink::HeapHashTableBacking<HashTable<ListHashSetNode<NodeContents, blink::HeapListHashSetAllocator<T, inlineCapacity>>*, U, V, W, X, Y, blink::HeapAllocator>>, void> {
+ using Node = ListHashSetNode<NodeContents, blink::HeapListHashSetAllocator<T, inlineCapacity>>;
+ using Table = HashTable<Node*, U, V, W, X, Y, blink::HeapAllocator>;
+
+ template<typename VisitorDispatcher>
+ static bool trace(VisitorDispatcher visitor, void* self)
+ {
+ Node** array = reinterpret_cast<Node**>(self);
+ blink::HeapObjectHeader* header = blink::HeapObjectHeader::fromPayload(self);
+ size_t length = header->payloadSize() / sizeof(Node*);
+ for (size_t i = 0; i < length; ++i) {
+ if (!HashTableHelper<Node*, typename Table::ExtractorType, typename Table::KeyTraitsType>::isEmptyOrDeletedBucket(array[i])) {
+ traceListHashSetValue(visitor, array[i]->m_value);
+ // Just mark the node without tracing because we already traced
+ // the contents, and there is no need to trace the next and
+ // prev fields since iterating over the hash table backing will
+ // find the whole chain.
+ visitor->markNoTracing(array[i]);
+ }
+ }
+ return false;
+ }
+};
+
+// Key value pairs, as used in HashMap. To disambiguate template choice we have
+// to have two versions, first the one with no special weak handling, then the
+// one with weak handling.
+template<ShouldWeakPointersBeMarkedStrongly strongify, typename Key, typename Value, typename Traits>
+struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, KeyValuePair<Key, Value>, Traits> {
+ template<typename VisitorDispatcher>
+ static bool trace(VisitorDispatcher visitor, KeyValuePair<Key, Value>& self)
+ {
+ ASSERT(ShouldBeTraced<Traits>::value);
+ blink::CollectionBackingTraceTrait<ShouldBeTraced<typename Traits::KeyTraits>::value, NoWeakHandlingInCollections, strongify, Key, typename Traits::KeyTraits>::trace(visitor, self.key);
+ blink::CollectionBackingTraceTrait<ShouldBeTraced<typename Traits::ValueTraits>::value, NoWeakHandlingInCollections, strongify, Value, typename Traits::ValueTraits>::trace(visitor, self.value);
+ return false;
+ }
+};
+
+template<ShouldWeakPointersBeMarkedStrongly strongify, typename Key, typename Value, typename Traits>
+struct TraceInCollectionTrait<WeakHandlingInCollections, strongify, KeyValuePair<Key, Value>, Traits> {
+ template<typename VisitorDispatcher>
+ static bool trace(VisitorDispatcher visitor, KeyValuePair<Key, Value>& self)
+ {
+ // This is the core of the ephemeron-like functionality. If there is
+ // weakness on the key side then we first check whether there are
+ // dead weak pointers on that side, and if there are we don't mark the
+ // value side (yet). Conversely if there is weakness on the value side
+ // we check that first and don't mark the key side yet if we find dead
+ // weak pointers.
+ // Corner case: If there is weakness on both the key and value side,
+ // and there are also strong pointers on the both sides then we could
+ // unexpectedly leak. The scenario is that the weak pointer on the key
+ // side is alive, which causes the strong pointer on the key side to be
+ // marked. If that then results in the object pointed to by the weak
+ // pointer on the value side being marked live, then the whole
+ // key-value entry is leaked. To avoid unexpected leaking, we disallow
+ // this case, but if you run into this assert, please reach out to Blink
+ // reviewers, and we may relax it.
+ const bool keyIsWeak = Traits::KeyTraits::weakHandlingFlag == WeakHandlingInCollections;
+ const bool valueIsWeak = Traits::ValueTraits::weakHandlingFlag == WeakHandlingInCollections;
+ const bool keyHasStrongRefs = ShouldBeTraced<typename Traits::KeyTraits>::value;
+ const bool valueHasStrongRefs = ShouldBeTraced<typename Traits::ValueTraits>::value;
+ static_assert(!keyIsWeak || !valueIsWeak || !keyHasStrongRefs || !valueHasStrongRefs, "this configuration is disallowed to avoid unexpected leaks");
+ if ((valueIsWeak && !keyIsWeak) || (valueIsWeak && keyIsWeak && !valueHasStrongRefs)) {
+ // Check value first.
+ bool deadWeakObjectsFoundOnValueSide = blink::CollectionBackingTraceTrait<ShouldBeTraced<typename Traits::ValueTraits>::value, Traits::ValueTraits::weakHandlingFlag, strongify, Value, typename Traits::ValueTraits>::trace(visitor, self.value);
+ if (deadWeakObjectsFoundOnValueSide)
+ return true;
+ return blink::CollectionBackingTraceTrait<ShouldBeTraced<typename Traits::KeyTraits>::value, Traits::KeyTraits::weakHandlingFlag, strongify, Key, typename Traits::KeyTraits>::trace(visitor, self.key);
+ }
+ // Check key first.
+ bool deadWeakObjectsFoundOnKeySide = blink::CollectionBackingTraceTrait<ShouldBeTraced<typename Traits::KeyTraits>::value, Traits::KeyTraits::weakHandlingFlag, strongify, Key, typename Traits::KeyTraits>::trace(visitor, self.key);
+ if (deadWeakObjectsFoundOnKeySide)
+ return true;
+ return blink::CollectionBackingTraceTrait<ShouldBeTraced<typename Traits::ValueTraits>::value, Traits::ValueTraits::weakHandlingFlag, strongify, Value, typename Traits::ValueTraits>::trace(visitor, self.value);
+ }
+};
+
+// Nodes used by LinkedHashSet. Again we need two versions to disambiguate the
+// template.
+template<ShouldWeakPointersBeMarkedStrongly strongify, typename Value, typename Allocator, typename Traits>
+struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, LinkedHashSetNode<Value, Allocator>, Traits> {
+ template<typename VisitorDispatcher>
+ static bool trace(VisitorDispatcher visitor, LinkedHashSetNode<Value, Allocator>& self)
+ {
+ ASSERT(ShouldBeTraced<Traits>::value);
+ return TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, Value, typename Traits::ValueTraits>::trace(visitor, self.m_value);
+ }
+};
+
+template<ShouldWeakPointersBeMarkedStrongly strongify, typename Value, typename Allocator, typename Traits>
+struct TraceInCollectionTrait<WeakHandlingInCollections, strongify, LinkedHashSetNode<Value, Allocator>, Traits> {
+ template<typename VisitorDispatcher>
+ static bool trace(VisitorDispatcher visitor, LinkedHashSetNode<Value, Allocator>& self)
+ {
+ return TraceInCollectionTrait<WeakHandlingInCollections, strongify, Value, typename Traits::ValueTraits>::trace(visitor, self.m_value);
+ }
+};
+
+// ListHashSetNode pointers (a ListHashSet is implemented as a hash table of
+// these pointers).
+template<ShouldWeakPointersBeMarkedStrongly strongify, typename Value, size_t inlineCapacity, typename Traits>
+struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, ListHashSetNode<Value, blink::HeapListHashSetAllocator<Value, inlineCapacity>>*, Traits> {
+ using Node = ListHashSetNode<Value, blink::HeapListHashSetAllocator<Value, inlineCapacity>>;
+
+ template<typename VisitorDispatcher>
+ static bool trace(VisitorDispatcher visitor, Node* node)
+ {
+ traceListHashSetValue(visitor, node->m_value);
+ // Just mark the node without tracing because we already traced the
+ // contents, and there is no need to trace the next and prev fields
+ // since iterating over the hash table backing will find the whole
+ // chain.
+ visitor->markNoTracing(node);
+ return false;
+ }
+};
+
+} // namespace WTF
+
+#endif
« no previous file with comments | « Source/platform/heap/InlinedGlobalMarkingVisitor.h ('k') | Source/platform/heap/Visitor.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698